mirror of
https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
synced 2025-10-29 15:28:50 +01:00
Fixed MTP to work with TWRP
This commit is contained in:
commit
f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions
133
arch/powerpc/platforms/83xx/Kconfig
Normal file
133
arch/powerpc/platforms/83xx/Kconfig
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
menuconfig PPC_83xx
|
||||
bool "83xx-based boards"
|
||||
depends on 6xx
|
||||
select PPC_UDBG_16550
|
||||
select PPC_PCI_CHOICE
|
||||
select FSL_PCI if PCI
|
||||
select FSL_SOC
|
||||
select IPIC
|
||||
|
||||
if PPC_83xx
|
||||
|
||||
config MPC830x_RDB
|
||||
bool "Freescale MPC830x RDB and derivatives"
|
||||
select DEFAULT_UIMAGE
|
||||
select PPC_MPC831x
|
||||
select FSL_GTM
|
||||
help
|
||||
This option enables support for the MPC8308 RDB and MPC8308 P1M boards.
|
||||
|
||||
config MPC831x_RDB
|
||||
bool "Freescale MPC831x RDB"
|
||||
select DEFAULT_UIMAGE
|
||||
select PPC_MPC831x
|
||||
help
|
||||
This option enables support for the MPC8313 RDB and MPC8315 RDB boards.
|
||||
|
||||
config MPC832x_MDS
|
||||
bool "Freescale MPC832x MDS"
|
||||
select DEFAULT_UIMAGE
|
||||
select PPC_MPC832x
|
||||
help
|
||||
This option enables support for the MPC832x MDS evaluation board.
|
||||
|
||||
config MPC832x_RDB
|
||||
bool "Freescale MPC832x RDB"
|
||||
select DEFAULT_UIMAGE
|
||||
select PPC_MPC832x
|
||||
help
|
||||
This option enables support for the MPC8323 RDB board.
|
||||
|
||||
config MPC834x_MDS
|
||||
bool "Freescale MPC834x MDS"
|
||||
select DEFAULT_UIMAGE
|
||||
select PPC_MPC834x
|
||||
help
|
||||
This option enables support for the MPC 834x MDS evaluation board.
|
||||
|
||||
Be aware that PCI buses can only function when MDS board is plugged
|
||||
into the PIB (Platform IO Board) board from Freescale which provide
|
||||
3 PCI slots. The PIBs PCI initialization is the bootloader's
|
||||
responsibility.
|
||||
|
||||
config MPC834x_ITX
|
||||
bool "Freescale MPC834x ITX"
|
||||
select DEFAULT_UIMAGE
|
||||
select PPC_MPC834x
|
||||
help
|
||||
This option enables support for the MPC 834x ITX evaluation board.
|
||||
|
||||
Be aware that PCI initialization is the bootloader's
|
||||
responsibility.
|
||||
|
||||
config MPC836x_MDS
|
||||
bool "Freescale MPC836x MDS"
|
||||
select DEFAULT_UIMAGE
|
||||
help
|
||||
This option enables support for the MPC836x MDS Processor Board.
|
||||
|
||||
config MPC836x_RDK
|
||||
bool "Freescale/Logic MPC836x RDK"
|
||||
select DEFAULT_UIMAGE
|
||||
select FSL_GTM
|
||||
select FSL_LBC
|
||||
help
|
||||
This option enables support for the MPC836x RDK Processor Board,
|
||||
also known as ZOOM PowerQUICC Kit.
|
||||
|
||||
config MPC837x_MDS
|
||||
bool "Freescale MPC837x MDS"
|
||||
select DEFAULT_UIMAGE
|
||||
select PPC_MPC837x
|
||||
help
|
||||
This option enables support for the MPC837x MDS Processor Board.
|
||||
|
||||
config MPC837x_RDB
|
||||
bool "Freescale MPC837x RDB/WLAN"
|
||||
select DEFAULT_UIMAGE
|
||||
select PPC_MPC837x
|
||||
help
|
||||
This option enables support for the MPC837x RDB and WLAN Boards.
|
||||
|
||||
config SBC834x
|
||||
bool "Wind River SBC834x"
|
||||
select DEFAULT_UIMAGE
|
||||
select PPC_MPC834x
|
||||
help
|
||||
This option enables support for the Wind River SBC834x board.
|
||||
|
||||
config ASP834x
|
||||
bool "Analogue & Micro ASP 834x"
|
||||
select PPC_MPC834x
|
||||
help
|
||||
This enables support for the Analogue & Micro ASP 83xx
|
||||
board.
|
||||
|
||||
config KMETER1
|
||||
bool "Keymile KMETER1"
|
||||
select DEFAULT_UIMAGE
|
||||
select QUICC_ENGINE
|
||||
help
|
||||
This enables support for the Keymile KMETER1 board.
|
||||
|
||||
|
||||
endif
|
||||
|
||||
# used for usb & gpio
|
||||
config PPC_MPC831x
|
||||
bool
|
||||
select ARCH_WANT_OPTIONAL_GPIOLIB
|
||||
|
||||
# used for math-emu
|
||||
config PPC_MPC832x
|
||||
bool
|
||||
|
||||
# used for usb & gpio
|
||||
config PPC_MPC834x
|
||||
bool
|
||||
select ARCH_WANT_OPTIONAL_GPIOLIB
|
||||
|
||||
# used for usb & gpio
|
||||
config PPC_MPC837x
|
||||
bool
|
||||
select ARCH_WANT_OPTIONAL_GPIOLIB
|
||||
19
arch/powerpc/platforms/83xx/Makefile
Normal file
19
arch/powerpc/platforms/83xx/Makefile
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# Makefile for the PowerPC 83xx linux kernel.
|
||||
#
|
||||
obj-y := misc.o usb.o
|
||||
obj-$(CONFIG_SUSPEND) += suspend.o suspend-asm.o
|
||||
obj-$(CONFIG_MCU_MPC8349EMITX) += mcu_mpc8349emitx.o
|
||||
obj-$(CONFIG_MPC830x_RDB) += mpc830x_rdb.o
|
||||
obj-$(CONFIG_MPC831x_RDB) += mpc831x_rdb.o
|
||||
obj-$(CONFIG_MPC832x_RDB) += mpc832x_rdb.o
|
||||
obj-$(CONFIG_MPC834x_MDS) += mpc834x_mds.o
|
||||
obj-$(CONFIG_MPC834x_ITX) += mpc834x_itx.o
|
||||
obj-$(CONFIG_MPC836x_MDS) += mpc836x_mds.o
|
||||
obj-$(CONFIG_MPC836x_RDK) += mpc836x_rdk.o
|
||||
obj-$(CONFIG_MPC832x_MDS) += mpc832x_mds.o
|
||||
obj-$(CONFIG_MPC837x_MDS) += mpc837x_mds.o
|
||||
obj-$(CONFIG_SBC834x) += sbc834x.o
|
||||
obj-$(CONFIG_MPC837x_RDB) += mpc837x_rdb.o
|
||||
obj-$(CONFIG_ASP834x) += asp834x.o
|
||||
obj-$(CONFIG_KMETER1) += km83xx.o
|
||||
60
arch/powerpc/platforms/83xx/asp834x.c
Normal file
60
arch/powerpc/platforms/83xx/asp834x.c
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* arch/powerpc/platforms/83xx/asp834x.c
|
||||
*
|
||||
* Analogue & Micro ASP8347 board specific routines
|
||||
* clone of mpc834x_itx
|
||||
*
|
||||
* Copyright 2008 Codehermit
|
||||
*
|
||||
* Maintainer: Bryan O'Donoghue <bodonoghue@codhermit.ie>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
||||
#include <asm/time.h>
|
||||
#include <asm/ipic.h>
|
||||
#include <asm/udbg.h>
|
||||
|
||||
#include "mpc83xx.h"
|
||||
|
||||
/* ************************************************************************
|
||||
*
|
||||
* Setup the architecture
|
||||
*
|
||||
*/
|
||||
static void __init asp834x_setup_arch(void)
|
||||
{
|
||||
if (ppc_md.progress)
|
||||
ppc_md.progress("asp834x_setup_arch()", 0);
|
||||
|
||||
mpc834x_usb_cfg();
|
||||
}
|
||||
|
||||
machine_device_initcall(asp834x, mpc83xx_declare_of_platform_devices);
|
||||
|
||||
/*
|
||||
* Called very early, MMU is off, device-tree isn't unflattened
|
||||
*/
|
||||
static int __init asp834x_probe(void)
|
||||
{
|
||||
unsigned long root = of_get_flat_dt_root();
|
||||
return of_flat_dt_is_compatible(root, "analogue-and-micro,asp8347e");
|
||||
}
|
||||
|
||||
define_machine(asp834x) {
|
||||
.name = "ASP8347E",
|
||||
.probe = asp834x_probe,
|
||||
.setup_arch = asp834x_setup_arch,
|
||||
.init_IRQ = mpc83xx_ipic_init_IRQ,
|
||||
.get_irq = ipic_get_irq,
|
||||
.restart = mpc83xx_restart,
|
||||
.time_init = mpc83xx_time_init,
|
||||
.calibrate_decr = generic_calibrate_decr,
|
||||
.progress = udbg_progress,
|
||||
};
|
||||
197
arch/powerpc/platforms/83xx/km83xx.c
Normal file
197
arch/powerpc/platforms/83xx/km83xx.c
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
* Copyright 2008-2011 DENX Software Engineering GmbH
|
||||
* Author: Heiko Schocher <hs@denx.de>
|
||||
*
|
||||
* Description:
|
||||
* Keymile 83xx platform specific routines.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/root_dev.h>
|
||||
#include <linux/initrd.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/ipic.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/udbg.h>
|
||||
#include <sysdev/fsl_soc.h>
|
||||
#include <sysdev/fsl_pci.h>
|
||||
#include <asm/qe.h>
|
||||
#include <asm/qe_ic.h>
|
||||
|
||||
#include "mpc83xx.h"
|
||||
|
||||
#define SVR_REV(svr) (((svr) >> 0) & 0xFFFF) /* Revision field */
|
||||
|
||||
static void quirk_mpc8360e_qe_enet10(void)
|
||||
{
|
||||
/*
|
||||
* handle mpc8360E Erratum QE_ENET10:
|
||||
* RGMII AC values do not meet the specification
|
||||
*/
|
||||
uint svid = mfspr(SPRN_SVR);
|
||||
struct device_node *np_par;
|
||||
struct resource res;
|
||||
void __iomem *base;
|
||||
int ret;
|
||||
|
||||
np_par = of_find_node_by_name(NULL, "par_io");
|
||||
if (np_par == NULL) {
|
||||
pr_warn("%s couldn;t find par_io node\n", __func__);
|
||||
return;
|
||||
}
|
||||
/* Map Parallel I/O ports registers */
|
||||
ret = of_address_to_resource(np_par, 0, &res);
|
||||
if (ret) {
|
||||
pr_warn("%s couldn;t map par_io registers\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
base = ioremap(res.start, res.end - res.start + 1);
|
||||
|
||||
/*
|
||||
* set output delay adjustments to default values according
|
||||
* table 5 in Errata Rev. 5, 9/2011:
|
||||
*
|
||||
* write 0b01 to UCC1 bits 18:19
|
||||
* write 0b01 to UCC2 option 1 bits 4:5
|
||||
* write 0b01 to UCC2 option 2 bits 16:17
|
||||
*/
|
||||
clrsetbits_be32((base + 0xa8), 0x0c00f000, 0x04005000);
|
||||
|
||||
/*
|
||||
* set output delay adjustments to default values according
|
||||
* table 3-13 in Reference Manual Rev.3 05/2010:
|
||||
*
|
||||
* write 0b01 to UCC2 option 2 bits 16:17
|
||||
* write 0b0101 to UCC1 bits 20:23
|
||||
* write 0b0101 to UCC2 option 1 bits 24:27
|
||||
*/
|
||||
clrsetbits_be32((base + 0xac), 0x0000cff0, 0x00004550);
|
||||
|
||||
if (SVR_REV(svid) == 0x0021) {
|
||||
/*
|
||||
* UCC2 option 1: write 0b1010 to bits 24:27
|
||||
* at address IMMRBAR+0x14AC
|
||||
*/
|
||||
clrsetbits_be32((base + 0xac), 0x000000f0, 0x000000a0);
|
||||
} else if (SVR_REV(svid) == 0x0020) {
|
||||
/*
|
||||
* UCC1: write 0b11 to bits 18:19
|
||||
* at address IMMRBAR+0x14A8
|
||||
*/
|
||||
setbits32((base + 0xa8), 0x00003000);
|
||||
|
||||
/*
|
||||
* UCC2 option 1: write 0b11 to bits 4:5
|
||||
* at address IMMRBAR+0x14A8
|
||||
*/
|
||||
setbits32((base + 0xa8), 0x0c000000);
|
||||
|
||||
/*
|
||||
* UCC2 option 2: write 0b11 to bits 16:17
|
||||
* at address IMMRBAR+0x14AC
|
||||
*/
|
||||
setbits32((base + 0xac), 0x0000c000);
|
||||
}
|
||||
iounmap(base);
|
||||
of_node_put(np_par);
|
||||
}
|
||||
|
||||
/* ************************************************************************
|
||||
*
|
||||
* Setup the architecture
|
||||
*
|
||||
*/
|
||||
static void __init mpc83xx_km_setup_arch(void)
|
||||
{
|
||||
#ifdef CONFIG_QUICC_ENGINE
|
||||
struct device_node *np;
|
||||
#endif
|
||||
|
||||
if (ppc_md.progress)
|
||||
ppc_md.progress("kmpbec83xx_setup_arch()", 0);
|
||||
|
||||
mpc83xx_setup_pci();
|
||||
|
||||
#ifdef CONFIG_QUICC_ENGINE
|
||||
qe_reset();
|
||||
|
||||
np = of_find_node_by_name(NULL, "par_io");
|
||||
if (np != NULL) {
|
||||
par_io_init(np);
|
||||
of_node_put(np);
|
||||
|
||||
for_each_node_by_name(np, "spi")
|
||||
par_io_of_config(np);
|
||||
|
||||
for_each_node_by_name(np, "ucc")
|
||||
par_io_of_config(np);
|
||||
|
||||
/* Only apply this quirk when par_io is available */
|
||||
np = of_find_compatible_node(NULL, "network", "ucc_geth");
|
||||
if (np != NULL) {
|
||||
quirk_mpc8360e_qe_enet10();
|
||||
of_node_put(np);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_QUICC_ENGINE */
|
||||
}
|
||||
|
||||
machine_device_initcall(mpc83xx_km, mpc83xx_declare_of_platform_devices);
|
||||
|
||||
/* list of the supported boards */
|
||||
static char *board[] __initdata = {
|
||||
"Keymile,KMETER1",
|
||||
"Keymile,kmpbec8321",
|
||||
NULL
|
||||
};
|
||||
|
||||
/*
|
||||
* Called very early, MMU is off, device-tree isn't unflattened
|
||||
*/
|
||||
static int __init mpc83xx_km_probe(void)
|
||||
{
|
||||
unsigned long node = of_get_flat_dt_root();
|
||||
int i = 0;
|
||||
|
||||
while (board[i]) {
|
||||
if (of_flat_dt_is_compatible(node, board[i]))
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
return (board[i] != NULL);
|
||||
}
|
||||
|
||||
define_machine(mpc83xx_km) {
|
||||
.name = "mpc83xx-km-platform",
|
||||
.probe = mpc83xx_km_probe,
|
||||
.setup_arch = mpc83xx_km_setup_arch,
|
||||
.init_IRQ = mpc83xx_ipic_and_qe_init_IRQ,
|
||||
.get_irq = ipic_get_irq,
|
||||
.restart = mpc83xx_restart,
|
||||
.time_init = mpc83xx_time_init,
|
||||
.calibrate_decr = generic_calibrate_decr,
|
||||
.progress = udbg_progress,
|
||||
};
|
||||
238
arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c
Normal file
238
arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c
Normal file
|
|
@ -0,0 +1,238 @@
|
|||
/*
|
||||
* Power Management and GPIO expander driver for MPC8349E-mITX-compatible MCU
|
||||
*
|
||||
* Copyright (c) 2008 MontaVista Software, Inc.
|
||||
*
|
||||
* Author: Anton Vorontsov <avorontsov@ru.mvista.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/machdep.h>
|
||||
|
||||
/*
|
||||
* I don't have specifications for the MCU firmware, I found this register
|
||||
* and bits positions by the trial&error method.
|
||||
*/
|
||||
#define MCU_REG_CTRL 0x20
|
||||
#define MCU_CTRL_POFF 0x40
|
||||
#define MCU_CTRL_BTN 0x80
|
||||
|
||||
#define MCU_NUM_GPIO 2
|
||||
|
||||
struct mcu {
|
||||
struct mutex lock;
|
||||
struct i2c_client *client;
|
||||
struct gpio_chip gc;
|
||||
u8 reg_ctrl;
|
||||
};
|
||||
|
||||
static struct mcu *glob_mcu;
|
||||
|
||||
struct task_struct *shutdown_thread;
|
||||
static int shutdown_thread_fn(void *data)
|
||||
{
|
||||
int ret;
|
||||
struct mcu *mcu = glob_mcu;
|
||||
|
||||
while (!kthread_should_stop()) {
|
||||
ret = i2c_smbus_read_byte_data(mcu->client, MCU_REG_CTRL);
|
||||
if (ret < 0)
|
||||
pr_err("MCU status reg read failed.\n");
|
||||
mcu->reg_ctrl = ret;
|
||||
|
||||
|
||||
if (mcu->reg_ctrl & MCU_CTRL_BTN) {
|
||||
i2c_smbus_write_byte_data(mcu->client, MCU_REG_CTRL,
|
||||
mcu->reg_ctrl & ~MCU_CTRL_BTN);
|
||||
|
||||
ctrl_alt_del();
|
||||
}
|
||||
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule_timeout(HZ);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t show_status(struct device *d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int ret;
|
||||
struct mcu *mcu = glob_mcu;
|
||||
|
||||
ret = i2c_smbus_read_byte_data(mcu->client, MCU_REG_CTRL);
|
||||
if (ret < 0)
|
||||
return -ENODEV;
|
||||
mcu->reg_ctrl = ret;
|
||||
|
||||
return sprintf(buf, "%02x\n", ret);
|
||||
}
|
||||
static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
|
||||
|
||||
static void mcu_power_off(void)
|
||||
{
|
||||
struct mcu *mcu = glob_mcu;
|
||||
|
||||
pr_info("Sending power-off request to the MCU...\n");
|
||||
mutex_lock(&mcu->lock);
|
||||
i2c_smbus_write_byte_data(mcu->client, MCU_REG_CTRL,
|
||||
mcu->reg_ctrl | MCU_CTRL_POFF);
|
||||
mutex_unlock(&mcu->lock);
|
||||
}
|
||||
|
||||
static void mcu_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
|
||||
{
|
||||
struct mcu *mcu = container_of(gc, struct mcu, gc);
|
||||
u8 bit = 1 << (4 + gpio);
|
||||
|
||||
mutex_lock(&mcu->lock);
|
||||
if (val)
|
||||
mcu->reg_ctrl &= ~bit;
|
||||
else
|
||||
mcu->reg_ctrl |= bit;
|
||||
|
||||
i2c_smbus_write_byte_data(mcu->client, MCU_REG_CTRL, mcu->reg_ctrl);
|
||||
mutex_unlock(&mcu->lock);
|
||||
}
|
||||
|
||||
static int mcu_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
|
||||
{
|
||||
mcu_gpio_set(gc, gpio, val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mcu_gpiochip_add(struct mcu *mcu)
|
||||
{
|
||||
struct device_node *np;
|
||||
struct gpio_chip *gc = &mcu->gc;
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "fsl,mcu-mpc8349emitx");
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
gc->owner = THIS_MODULE;
|
||||
gc->label = np->full_name;
|
||||
gc->can_sleep = 1;
|
||||
gc->ngpio = MCU_NUM_GPIO;
|
||||
gc->base = -1;
|
||||
gc->set = mcu_gpio_set;
|
||||
gc->direction_output = mcu_gpio_dir_out;
|
||||
gc->of_node = np;
|
||||
|
||||
return gpiochip_add(gc);
|
||||
}
|
||||
|
||||
static int mcu_gpiochip_remove(struct mcu *mcu)
|
||||
{
|
||||
gpiochip_remove(&mcu->gc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mcu_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
{
|
||||
struct mcu *mcu;
|
||||
int ret;
|
||||
|
||||
mcu = kzalloc(sizeof(*mcu), GFP_KERNEL);
|
||||
if (!mcu)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&mcu->lock);
|
||||
mcu->client = client;
|
||||
i2c_set_clientdata(client, mcu);
|
||||
|
||||
ret = i2c_smbus_read_byte_data(mcu->client, MCU_REG_CTRL);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
mcu->reg_ctrl = ret;
|
||||
|
||||
ret = mcu_gpiochip_add(mcu);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
/* XXX: this is potentially racy, but there is no lock for ppc_md */
|
||||
if (!ppc_md.power_off) {
|
||||
glob_mcu = mcu;
|
||||
ppc_md.power_off = mcu_power_off;
|
||||
dev_info(&client->dev, "will provide power-off service\n");
|
||||
}
|
||||
|
||||
if (device_create_file(&client->dev, &dev_attr_status))
|
||||
dev_err(&client->dev,
|
||||
"couldn't create device file for status\n");
|
||||
|
||||
shutdown_thread = kthread_run(shutdown_thread_fn, NULL,
|
||||
"mcu-i2c-shdn");
|
||||
|
||||
return 0;
|
||||
err:
|
||||
kfree(mcu);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mcu_remove(struct i2c_client *client)
|
||||
{
|
||||
struct mcu *mcu = i2c_get_clientdata(client);
|
||||
int ret;
|
||||
|
||||
kthread_stop(shutdown_thread);
|
||||
|
||||
device_remove_file(&client->dev, &dev_attr_status);
|
||||
|
||||
if (glob_mcu == mcu) {
|
||||
ppc_md.power_off = NULL;
|
||||
glob_mcu = NULL;
|
||||
}
|
||||
|
||||
ret = mcu_gpiochip_remove(mcu);
|
||||
if (ret)
|
||||
return ret;
|
||||
kfree(mcu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id mcu_ids[] = {
|
||||
{ "mcu-mpc8349emitx", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, mcu_ids);
|
||||
|
||||
static const struct of_device_id mcu_of_match_table[] = {
|
||||
{ .compatible = "fsl,mcu-mpc8349emitx", },
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct i2c_driver mcu_driver = {
|
||||
.driver = {
|
||||
.name = "mcu-mpc8349emitx",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = mcu_of_match_table,
|
||||
},
|
||||
.probe = mcu_probe,
|
||||
.remove = mcu_remove,
|
||||
.id_table = mcu_ids,
|
||||
};
|
||||
|
||||
module_i2c_driver(mcu_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Power Management and GPIO expander driver for "
|
||||
"MPC8349E-mITX-compatible MCU");
|
||||
MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
144
arch/powerpc/platforms/83xx/misc.c
Normal file
144
arch/powerpc/platforms/83xx/misc.c
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* misc setup functions for MPC83xx
|
||||
*
|
||||
* Maintainer: Kumar Gala <galak@kernel.crashing.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/hw_irq.h>
|
||||
#include <asm/ipic.h>
|
||||
#include <asm/qe_ic.h>
|
||||
#include <sysdev/fsl_soc.h>
|
||||
#include <sysdev/fsl_pci.h>
|
||||
|
||||
#include "mpc83xx.h"
|
||||
|
||||
static __be32 __iomem *restart_reg_base;
|
||||
|
||||
static int __init mpc83xx_restart_init(void)
|
||||
{
|
||||
/* map reset restart_reg_baseister space */
|
||||
restart_reg_base = ioremap(get_immrbase() + 0x900, 0xff);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
arch_initcall(mpc83xx_restart_init);
|
||||
|
||||
void mpc83xx_restart(char *cmd)
|
||||
{
|
||||
#define RST_OFFSET 0x00000900
|
||||
#define RST_PROT_REG 0x00000018
|
||||
#define RST_CTRL_REG 0x0000001c
|
||||
|
||||
local_irq_disable();
|
||||
|
||||
if (restart_reg_base) {
|
||||
/* enable software reset "RSTE" */
|
||||
out_be32(restart_reg_base + (RST_PROT_REG >> 2), 0x52535445);
|
||||
|
||||
/* set software hard reset */
|
||||
out_be32(restart_reg_base + (RST_CTRL_REG >> 2), 0x2);
|
||||
} else {
|
||||
printk (KERN_EMERG "Error: Restart registers not mapped, spinning!\n");
|
||||
}
|
||||
|
||||
for (;;) ;
|
||||
}
|
||||
|
||||
long __init mpc83xx_time_init(void)
|
||||
{
|
||||
#define SPCR_OFFSET 0x00000110
|
||||
#define SPCR_TBEN 0x00400000
|
||||
__be32 __iomem *spcr = ioremap(get_immrbase() + SPCR_OFFSET, 4);
|
||||
__be32 tmp;
|
||||
|
||||
tmp = in_be32(spcr);
|
||||
out_be32(spcr, tmp | SPCR_TBEN);
|
||||
|
||||
iounmap(spcr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __init mpc83xx_ipic_init_IRQ(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
||||
/* looking for fsl,pq2pro-pic which is asl compatible with fsl,ipic */
|
||||
np = of_find_compatible_node(NULL, NULL, "fsl,ipic");
|
||||
if (!np)
|
||||
np = of_find_node_by_type(NULL, "ipic");
|
||||
if (!np)
|
||||
return;
|
||||
|
||||
ipic_init(np, 0);
|
||||
|
||||
of_node_put(np);
|
||||
|
||||
/* Initialize the default interrupt mapping priorities,
|
||||
* in case the boot rom changed something on us.
|
||||
*/
|
||||
ipic_set_default_priority();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_QUICC_ENGINE
|
||||
void __init mpc83xx_qe_init_IRQ(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
|
||||
if (!np) {
|
||||
np = of_find_node_by_type(NULL, "qeic");
|
||||
if (!np)
|
||||
return;
|
||||
}
|
||||
qe_ic_init(np, 0, qe_ic_cascade_low_ipic, qe_ic_cascade_high_ipic);
|
||||
of_node_put(np);
|
||||
}
|
||||
|
||||
void __init mpc83xx_ipic_and_qe_init_IRQ(void)
|
||||
{
|
||||
mpc83xx_ipic_init_IRQ();
|
||||
mpc83xx_qe_init_IRQ();
|
||||
}
|
||||
#endif /* CONFIG_QUICC_ENGINE */
|
||||
|
||||
static const struct of_device_id of_bus_ids[] __initconst = {
|
||||
{ .type = "soc", },
|
||||
{ .compatible = "soc", },
|
||||
{ .compatible = "simple-bus" },
|
||||
{ .compatible = "gianfar" },
|
||||
{ .compatible = "gpio-leds", },
|
||||
{ .type = "qe", },
|
||||
{ .compatible = "fsl,qe", },
|
||||
{},
|
||||
};
|
||||
|
||||
int __init mpc83xx_declare_of_platform_devices(void)
|
||||
{
|
||||
of_platform_bus_probe(NULL, of_bus_ids, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
void __init mpc83xx_setup_pci(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
||||
for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
|
||||
mpc83xx_add_bridge(np);
|
||||
for_each_compatible_node(np, "pci", "fsl,mpc8314-pcie")
|
||||
mpc83xx_add_bridge(np);
|
||||
}
|
||||
#endif
|
||||
64
arch/powerpc/platforms/83xx/mpc830x_rdb.c
Normal file
64
arch/powerpc/platforms/83xx/mpc830x_rdb.c
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* arch/powerpc/platforms/83xx/mpc830x_rdb.c
|
||||
*
|
||||
* Description: MPC830x RDB board specific routines.
|
||||
* This file is based on mpc831x_rdb.c
|
||||
*
|
||||
* Copyright (C) Freescale Semiconductor, Inc. 2009. All rights reserved.
|
||||
* Copyright (C) 2010. Ilya Yanok, Emcraft Systems, yanok@emcraft.com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/ipic.h>
|
||||
#include <asm/udbg.h>
|
||||
#include <sysdev/fsl_pci.h>
|
||||
#include <sysdev/fsl_soc.h>
|
||||
#include "mpc83xx.h"
|
||||
|
||||
/*
|
||||
* Setup the architecture
|
||||
*/
|
||||
static void __init mpc830x_rdb_setup_arch(void)
|
||||
{
|
||||
if (ppc_md.progress)
|
||||
ppc_md.progress("mpc830x_rdb_setup_arch()", 0);
|
||||
|
||||
mpc83xx_setup_pci();
|
||||
mpc831x_usb_cfg();
|
||||
}
|
||||
|
||||
static const char *board[] __initdata = {
|
||||
"MPC8308RDB",
|
||||
"fsl,mpc8308rdb",
|
||||
"denx,mpc8308_p1m",
|
||||
NULL
|
||||
};
|
||||
|
||||
/*
|
||||
* Called very early, MMU is off, device-tree isn't unflattened
|
||||
*/
|
||||
static int __init mpc830x_rdb_probe(void)
|
||||
{
|
||||
return of_flat_dt_match(of_get_flat_dt_root(), board);
|
||||
}
|
||||
|
||||
machine_device_initcall(mpc830x_rdb, mpc83xx_declare_of_platform_devices);
|
||||
|
||||
define_machine(mpc830x_rdb) {
|
||||
.name = "MPC830x RDB",
|
||||
.probe = mpc830x_rdb_probe,
|
||||
.setup_arch = mpc830x_rdb_setup_arch,
|
||||
.init_IRQ = mpc83xx_ipic_init_IRQ,
|
||||
.get_irq = ipic_get_irq,
|
||||
.restart = mpc83xx_restart,
|
||||
.time_init = mpc83xx_time_init,
|
||||
.calibrate_decr = generic_calibrate_decr,
|
||||
.progress = udbg_progress,
|
||||
};
|
||||
64
arch/powerpc/platforms/83xx/mpc831x_rdb.c
Normal file
64
arch/powerpc/platforms/83xx/mpc831x_rdb.c
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* arch/powerpc/platforms/83xx/mpc831x_rdb.c
|
||||
*
|
||||
* Description: MPC831x RDB board specific routines.
|
||||
* This file is based on mpc834x_sys.c
|
||||
* Author: Lo Wlison <r43300@freescale.com>
|
||||
*
|
||||
* Copyright (C) Freescale Semiconductor, Inc. 2006. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
||||
#include <asm/time.h>
|
||||
#include <asm/ipic.h>
|
||||
#include <asm/udbg.h>
|
||||
#include <sysdev/fsl_pci.h>
|
||||
|
||||
#include "mpc83xx.h"
|
||||
|
||||
/*
|
||||
* Setup the architecture
|
||||
*/
|
||||
static void __init mpc831x_rdb_setup_arch(void)
|
||||
{
|
||||
if (ppc_md.progress)
|
||||
ppc_md.progress("mpc831x_rdb_setup_arch()", 0);
|
||||
|
||||
mpc83xx_setup_pci();
|
||||
mpc831x_usb_cfg();
|
||||
}
|
||||
|
||||
static const char *board[] __initdata = {
|
||||
"MPC8313ERDB",
|
||||
"fsl,mpc8315erdb",
|
||||
NULL
|
||||
};
|
||||
|
||||
/*
|
||||
* Called very early, MMU is off, device-tree isn't unflattened
|
||||
*/
|
||||
static int __init mpc831x_rdb_probe(void)
|
||||
{
|
||||
return of_flat_dt_match(of_get_flat_dt_root(), board);
|
||||
}
|
||||
|
||||
machine_device_initcall(mpc831x_rdb, mpc83xx_declare_of_platform_devices);
|
||||
|
||||
define_machine(mpc831x_rdb) {
|
||||
.name = "MPC831x RDB",
|
||||
.probe = mpc831x_rdb_probe,
|
||||
.setup_arch = mpc831x_rdb_setup_arch,
|
||||
.init_IRQ = mpc83xx_ipic_init_IRQ,
|
||||
.get_irq = ipic_get_irq,
|
||||
.restart = mpc83xx_restart,
|
||||
.time_init = mpc83xx_time_init,
|
||||
.calibrate_decr = generic_calibrate_decr,
|
||||
.progress = udbg_progress,
|
||||
};
|
||||
122
arch/powerpc/platforms/83xx/mpc832x_mds.c
Normal file
122
arch/powerpc/platforms/83xx/mpc832x_mds.c
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Copyright 2006 Freescale Semiconductor, Inc. All rights reserved.
|
||||
*
|
||||
* Description:
|
||||
* MPC832xE MDS board specific routines.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/root_dev.h>
|
||||
#include <linux/initrd.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
#include <linux/atomic.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/ipic.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/udbg.h>
|
||||
#include <sysdev/fsl_soc.h>
|
||||
#include <sysdev/fsl_pci.h>
|
||||
#include <asm/qe.h>
|
||||
#include <asm/qe_ic.h>
|
||||
|
||||
#include "mpc83xx.h"
|
||||
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
#define DBG(fmt...) udbg_printf(fmt)
|
||||
#else
|
||||
#define DBG(fmt...)
|
||||
#endif
|
||||
|
||||
/* ************************************************************************
|
||||
*
|
||||
* Setup the architecture
|
||||
*
|
||||
*/
|
||||
static void __init mpc832x_sys_setup_arch(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
u8 __iomem *bcsr_regs = NULL;
|
||||
|
||||
if (ppc_md.progress)
|
||||
ppc_md.progress("mpc832x_sys_setup_arch()", 0);
|
||||
|
||||
/* Map BCSR area */
|
||||
np = of_find_node_by_name(NULL, "bcsr");
|
||||
if (np) {
|
||||
struct resource res;
|
||||
|
||||
of_address_to_resource(np, 0, &res);
|
||||
bcsr_regs = ioremap(res.start, resource_size(&res));
|
||||
of_node_put(np);
|
||||
}
|
||||
|
||||
mpc83xx_setup_pci();
|
||||
|
||||
#ifdef CONFIG_QUICC_ENGINE
|
||||
qe_reset();
|
||||
|
||||
if ((np = of_find_node_by_name(NULL, "par_io")) != NULL) {
|
||||
par_io_init(np);
|
||||
of_node_put(np);
|
||||
|
||||
for (np = NULL; (np = of_find_node_by_name(np, "ucc")) != NULL;)
|
||||
par_io_of_config(np);
|
||||
}
|
||||
|
||||
if ((np = of_find_compatible_node(NULL, "network", "ucc_geth"))
|
||||
!= NULL){
|
||||
/* Reset the Ethernet PHYs */
|
||||
#define BCSR8_FETH_RST 0x50
|
||||
clrbits8(&bcsr_regs[8], BCSR8_FETH_RST);
|
||||
udelay(1000);
|
||||
setbits8(&bcsr_regs[8], BCSR8_FETH_RST);
|
||||
iounmap(bcsr_regs);
|
||||
of_node_put(np);
|
||||
}
|
||||
#endif /* CONFIG_QUICC_ENGINE */
|
||||
}
|
||||
|
||||
machine_device_initcall(mpc832x_mds, mpc83xx_declare_of_platform_devices);
|
||||
|
||||
/*
|
||||
* Called very early, MMU is off, device-tree isn't unflattened
|
||||
*/
|
||||
static int __init mpc832x_sys_probe(void)
|
||||
{
|
||||
unsigned long root = of_get_flat_dt_root();
|
||||
|
||||
return of_flat_dt_is_compatible(root, "MPC832xMDS");
|
||||
}
|
||||
|
||||
define_machine(mpc832x_mds) {
|
||||
.name = "MPC832x MDS",
|
||||
.probe = mpc832x_sys_probe,
|
||||
.setup_arch = mpc832x_sys_setup_arch,
|
||||
.init_IRQ = mpc83xx_ipic_and_qe_init_IRQ,
|
||||
.get_irq = ipic_get_irq,
|
||||
.restart = mpc83xx_restart,
|
||||
.time_init = mpc83xx_time_init,
|
||||
.calibrate_decr = generic_calibrate_decr,
|
||||
.progress = udbg_progress,
|
||||
};
|
||||
240
arch/powerpc/platforms/83xx/mpc832x_rdb.c
Normal file
240
arch/powerpc/platforms/83xx/mpc832x_rdb.c
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
/*
|
||||
* arch/powerpc/platforms/83xx/mpc832x_rdb.c
|
||||
*
|
||||
* Copyright (C) Freescale Semiconductor, Inc. 2007. All rights reserved.
|
||||
*
|
||||
* Description:
|
||||
* MPC832x RDB board specific routines.
|
||||
* This file is based on mpc832x_mds.c and mpc8313_rdb.c
|
||||
* Author: Michael Barkowski <michael.barkowski@freescale.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/mmc_spi.h>
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/fsl_devices.h>
|
||||
|
||||
#include <asm/time.h>
|
||||
#include <asm/ipic.h>
|
||||
#include <asm/udbg.h>
|
||||
#include <asm/qe.h>
|
||||
#include <asm/qe_ic.h>
|
||||
#include <sysdev/fsl_soc.h>
|
||||
#include <sysdev/fsl_pci.h>
|
||||
|
||||
#include "mpc83xx.h"
|
||||
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
#define DBG(fmt...) udbg_printf(fmt)
|
||||
#else
|
||||
#define DBG(fmt...)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_QUICC_ENGINE
|
||||
static int __init of_fsl_spi_probe(char *type, char *compatible, u32 sysclk,
|
||||
struct spi_board_info *board_infos,
|
||||
unsigned int num_board_infos,
|
||||
void (*cs_control)(struct spi_device *dev,
|
||||
bool on))
|
||||
{
|
||||
struct device_node *np;
|
||||
unsigned int i = 0;
|
||||
|
||||
for_each_compatible_node(np, type, compatible) {
|
||||
int ret;
|
||||
unsigned int j;
|
||||
const void *prop;
|
||||
struct resource res[2];
|
||||
struct platform_device *pdev;
|
||||
struct fsl_spi_platform_data pdata = {
|
||||
.cs_control = cs_control,
|
||||
};
|
||||
|
||||
memset(res, 0, sizeof(res));
|
||||
|
||||
pdata.sysclk = sysclk;
|
||||
|
||||
prop = of_get_property(np, "reg", NULL);
|
||||
if (!prop)
|
||||
goto err;
|
||||
pdata.bus_num = *(u32 *)prop;
|
||||
|
||||
prop = of_get_property(np, "cell-index", NULL);
|
||||
if (prop)
|
||||
i = *(u32 *)prop;
|
||||
|
||||
prop = of_get_property(np, "mode", NULL);
|
||||
if (prop && !strcmp(prop, "cpu-qe"))
|
||||
pdata.flags = SPI_QE_CPU_MODE;
|
||||
|
||||
for (j = 0; j < num_board_infos; j++) {
|
||||
if (board_infos[j].bus_num == pdata.bus_num)
|
||||
pdata.max_chipselect++;
|
||||
}
|
||||
|
||||
if (!pdata.max_chipselect)
|
||||
continue;
|
||||
|
||||
ret = of_address_to_resource(np, 0, &res[0]);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = of_irq_to_resource(np, 0, &res[1]);
|
||||
if (ret == NO_IRQ)
|
||||
goto err;
|
||||
|
||||
pdev = platform_device_alloc("mpc83xx_spi", i);
|
||||
if (!pdev)
|
||||
goto err;
|
||||
|
||||
ret = platform_device_add_data(pdev, &pdata, sizeof(pdata));
|
||||
if (ret)
|
||||
goto unreg;
|
||||
|
||||
ret = platform_device_add_resources(pdev, res,
|
||||
ARRAY_SIZE(res));
|
||||
if (ret)
|
||||
goto unreg;
|
||||
|
||||
ret = platform_device_add(pdev);
|
||||
if (ret)
|
||||
goto unreg;
|
||||
|
||||
goto next;
|
||||
unreg:
|
||||
platform_device_del(pdev);
|
||||
err:
|
||||
pr_err("%s: registration failed\n", np->full_name);
|
||||
next:
|
||||
i++;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static int __init fsl_spi_init(struct spi_board_info *board_infos,
|
||||
unsigned int num_board_infos,
|
||||
void (*cs_control)(struct spi_device *spi,
|
||||
bool on))
|
||||
{
|
||||
u32 sysclk = -1;
|
||||
int ret;
|
||||
|
||||
/* SPI controller is either clocked from QE or SoC clock */
|
||||
sysclk = get_brgfreq();
|
||||
if (sysclk == -1) {
|
||||
sysclk = fsl_get_sys_freq();
|
||||
if (sysclk == -1)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = of_fsl_spi_probe(NULL, "fsl,spi", sysclk, board_infos,
|
||||
num_board_infos, cs_control);
|
||||
if (!ret)
|
||||
of_fsl_spi_probe("spi", "fsl_spi", sysclk, board_infos,
|
||||
num_board_infos, cs_control);
|
||||
|
||||
return spi_register_board_info(board_infos, num_board_infos);
|
||||
}
|
||||
|
||||
static void mpc83xx_spi_cs_control(struct spi_device *spi, bool on)
|
||||
{
|
||||
pr_debug("%s %d %d\n", __func__, spi->chip_select, on);
|
||||
par_io_data_set(3, 13, on);
|
||||
}
|
||||
|
||||
static struct mmc_spi_platform_data mpc832x_mmc_pdata = {
|
||||
.ocr_mask = MMC_VDD_33_34,
|
||||
};
|
||||
|
||||
static struct spi_board_info mpc832x_spi_boardinfo = {
|
||||
.bus_num = 0x4c0,
|
||||
.chip_select = 0,
|
||||
.max_speed_hz = 50000000,
|
||||
.modalias = "mmc_spi",
|
||||
.platform_data = &mpc832x_mmc_pdata,
|
||||
};
|
||||
|
||||
static int __init mpc832x_spi_init(void)
|
||||
{
|
||||
par_io_config_pin(3, 0, 3, 0, 1, 0); /* SPI1 MOSI, I/O */
|
||||
par_io_config_pin(3, 1, 3, 0, 1, 0); /* SPI1 MISO, I/O */
|
||||
par_io_config_pin(3, 2, 3, 0, 1, 0); /* SPI1 CLK, I/O */
|
||||
par_io_config_pin(3, 3, 2, 0, 1, 0); /* SPI1 SEL, I */
|
||||
|
||||
par_io_config_pin(3, 13, 1, 0, 0, 0); /* !SD_CS, O */
|
||||
par_io_config_pin(3, 14, 2, 0, 0, 0); /* SD_INSERT, I */
|
||||
par_io_config_pin(3, 15, 2, 0, 0, 0); /* SD_PROTECT,I */
|
||||
|
||||
/*
|
||||
* Don't bother with legacy stuff when device tree contains
|
||||
* mmc-spi-slot node.
|
||||
*/
|
||||
if (of_find_compatible_node(NULL, NULL, "mmc-spi-slot"))
|
||||
return 0;
|
||||
return fsl_spi_init(&mpc832x_spi_boardinfo, 1, mpc83xx_spi_cs_control);
|
||||
}
|
||||
machine_device_initcall(mpc832x_rdb, mpc832x_spi_init);
|
||||
#endif /* CONFIG_QUICC_ENGINE */
|
||||
|
||||
/* ************************************************************************
|
||||
*
|
||||
* Setup the architecture
|
||||
*
|
||||
*/
|
||||
static void __init mpc832x_rdb_setup_arch(void)
|
||||
{
|
||||
#if defined(CONFIG_QUICC_ENGINE)
|
||||
struct device_node *np;
|
||||
#endif
|
||||
|
||||
if (ppc_md.progress)
|
||||
ppc_md.progress("mpc832x_rdb_setup_arch()", 0);
|
||||
|
||||
mpc83xx_setup_pci();
|
||||
|
||||
#ifdef CONFIG_QUICC_ENGINE
|
||||
qe_reset();
|
||||
|
||||
if ((np = of_find_node_by_name(NULL, "par_io")) != NULL) {
|
||||
par_io_init(np);
|
||||
of_node_put(np);
|
||||
|
||||
for (np = NULL; (np = of_find_node_by_name(np, "ucc")) != NULL;)
|
||||
par_io_of_config(np);
|
||||
}
|
||||
#endif /* CONFIG_QUICC_ENGINE */
|
||||
}
|
||||
|
||||
machine_device_initcall(mpc832x_rdb, mpc83xx_declare_of_platform_devices);
|
||||
|
||||
/*
|
||||
* Called very early, MMU is off, device-tree isn't unflattened
|
||||
*/
|
||||
static int __init mpc832x_rdb_probe(void)
|
||||
{
|
||||
unsigned long root = of_get_flat_dt_root();
|
||||
|
||||
return of_flat_dt_is_compatible(root, "MPC832xRDB");
|
||||
}
|
||||
|
||||
define_machine(mpc832x_rdb) {
|
||||
.name = "MPC832x RDB",
|
||||
.probe = mpc832x_rdb_probe,
|
||||
.setup_arch = mpc832x_rdb_setup_arch,
|
||||
.init_IRQ = mpc83xx_ipic_and_qe_init_IRQ,
|
||||
.get_irq = ipic_get_irq,
|
||||
.restart = mpc83xx_restart,
|
||||
.time_init = mpc83xx_time_init,
|
||||
.calibrate_decr = generic_calibrate_decr,
|
||||
.progress = udbg_progress,
|
||||
};
|
||||
88
arch/powerpc/platforms/83xx/mpc834x_itx.c
Normal file
88
arch/powerpc/platforms/83xx/mpc834x_itx.c
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* arch/powerpc/platforms/83xx/mpc834x_itx.c
|
||||
*
|
||||
* MPC834x ITX board specific routines
|
||||
*
|
||||
* Maintainer: Kumar Gala <galak@kernel.crashing.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/root_dev.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
||||
#include <linux/atomic.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/ipic.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/udbg.h>
|
||||
#include <sysdev/fsl_soc.h>
|
||||
#include <sysdev/fsl_pci.h>
|
||||
|
||||
#include "mpc83xx.h"
|
||||
|
||||
static const struct of_device_id mpc834x_itx_ids[] __initconst = {
|
||||
{ .compatible = "fsl,pq2pro-localbus", },
|
||||
{},
|
||||
};
|
||||
|
||||
static int __init mpc834x_itx_declare_of_platform_devices(void)
|
||||
{
|
||||
mpc83xx_declare_of_platform_devices();
|
||||
return of_platform_bus_probe(NULL, mpc834x_itx_ids, NULL);
|
||||
}
|
||||
machine_device_initcall(mpc834x_itx, mpc834x_itx_declare_of_platform_devices);
|
||||
|
||||
/* ************************************************************************
|
||||
*
|
||||
* Setup the architecture
|
||||
*
|
||||
*/
|
||||
static void __init mpc834x_itx_setup_arch(void)
|
||||
{
|
||||
if (ppc_md.progress)
|
||||
ppc_md.progress("mpc834x_itx_setup_arch()", 0);
|
||||
|
||||
mpc83xx_setup_pci();
|
||||
|
||||
mpc834x_usb_cfg();
|
||||
}
|
||||
|
||||
/*
|
||||
* Called very early, MMU is off, device-tree isn't unflattened
|
||||
*/
|
||||
static int __init mpc834x_itx_probe(void)
|
||||
{
|
||||
unsigned long root = of_get_flat_dt_root();
|
||||
|
||||
return of_flat_dt_is_compatible(root, "MPC834xMITX");
|
||||
}
|
||||
|
||||
define_machine(mpc834x_itx) {
|
||||
.name = "MPC834x ITX",
|
||||
.probe = mpc834x_itx_probe,
|
||||
.setup_arch = mpc834x_itx_setup_arch,
|
||||
.init_IRQ = mpc83xx_ipic_init_IRQ,
|
||||
.get_irq = ipic_get_irq,
|
||||
.restart = mpc83xx_restart,
|
||||
.time_init = mpc83xx_time_init,
|
||||
.calibrate_decr = generic_calibrate_decr,
|
||||
.progress = udbg_progress,
|
||||
};
|
||||
109
arch/powerpc/platforms/83xx/mpc834x_mds.c
Normal file
109
arch/powerpc/platforms/83xx/mpc834x_mds.c
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* arch/powerpc/platforms/83xx/mpc834x_mds.c
|
||||
*
|
||||
* MPC834x MDS board specific routines
|
||||
*
|
||||
* Maintainer: Kumar Gala <galak@kernel.crashing.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/root_dev.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
||||
#include <linux/atomic.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/ipic.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/udbg.h>
|
||||
#include <sysdev/fsl_soc.h>
|
||||
#include <sysdev/fsl_pci.h>
|
||||
|
||||
#include "mpc83xx.h"
|
||||
|
||||
#define BCSR5_INT_USB 0x02
|
||||
static int mpc834xemds_usb_cfg(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
void __iomem *bcsr_regs = NULL;
|
||||
u8 bcsr5;
|
||||
|
||||
mpc834x_usb_cfg();
|
||||
/* Map BCSR area */
|
||||
np = of_find_node_by_name(NULL, "bcsr");
|
||||
if (np) {
|
||||
struct resource res;
|
||||
|
||||
of_address_to_resource(np, 0, &res);
|
||||
bcsr_regs = ioremap(res.start, resource_size(&res));
|
||||
of_node_put(np);
|
||||
}
|
||||
if (!bcsr_regs)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* if Processor Board is plugged into PIB board,
|
||||
* force to use the PHY on Processor Board
|
||||
*/
|
||||
bcsr5 = in_8(bcsr_regs + 5);
|
||||
if (!(bcsr5 & BCSR5_INT_USB))
|
||||
out_8(bcsr_regs + 5, (bcsr5 | BCSR5_INT_USB));
|
||||
iounmap(bcsr_regs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ************************************************************************
|
||||
*
|
||||
* Setup the architecture
|
||||
*
|
||||
*/
|
||||
static void __init mpc834x_mds_setup_arch(void)
|
||||
{
|
||||
if (ppc_md.progress)
|
||||
ppc_md.progress("mpc834x_mds_setup_arch()", 0);
|
||||
|
||||
mpc83xx_setup_pci();
|
||||
|
||||
mpc834xemds_usb_cfg();
|
||||
}
|
||||
|
||||
machine_device_initcall(mpc834x_mds, mpc83xx_declare_of_platform_devices);
|
||||
|
||||
/*
|
||||
* Called very early, MMU is off, device-tree isn't unflattened
|
||||
*/
|
||||
static int __init mpc834x_mds_probe(void)
|
||||
{
|
||||
unsigned long root = of_get_flat_dt_root();
|
||||
|
||||
return of_flat_dt_is_compatible(root, "MPC834xMDS");
|
||||
}
|
||||
|
||||
define_machine(mpc834x_mds) {
|
||||
.name = "MPC834x MDS",
|
||||
.probe = mpc834x_mds_probe,
|
||||
.setup_arch = mpc834x_mds_setup_arch,
|
||||
.init_IRQ = mpc83xx_ipic_init_IRQ,
|
||||
.get_irq = ipic_get_irq,
|
||||
.restart = mpc83xx_restart,
|
||||
.time_init = mpc83xx_time_init,
|
||||
.calibrate_decr = generic_calibrate_decr,
|
||||
.progress = udbg_progress,
|
||||
};
|
||||
229
arch/powerpc/platforms/83xx/mpc836x_mds.c
Normal file
229
arch/powerpc/platforms/83xx/mpc836x_mds.c
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
* Copyright 2006 Freescale Semiconductor, Inc. All rights reserved.
|
||||
*
|
||||
* Author: Li Yang <LeoLi@freescale.com>
|
||||
* Yin Olivia <Hong-hua.Yin@freescale.com>
|
||||
*
|
||||
* Description:
|
||||
* MPC8360E MDS board specific routines.
|
||||
*
|
||||
* Changelog:
|
||||
* Jun 21, 2006 Initial version
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/root_dev.h>
|
||||
#include <linux/initrd.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
#include <linux/atomic.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/ipic.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/udbg.h>
|
||||
#include <sysdev/fsl_soc.h>
|
||||
#include <sysdev/fsl_pci.h>
|
||||
#include <sysdev/simple_gpio.h>
|
||||
#include <asm/qe.h>
|
||||
#include <asm/qe_ic.h>
|
||||
|
||||
#include "mpc83xx.h"
|
||||
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
#define DBG(fmt...) udbg_printf(fmt)
|
||||
#else
|
||||
#define DBG(fmt...)
|
||||
#endif
|
||||
|
||||
/* ************************************************************************
|
||||
*
|
||||
* Setup the architecture
|
||||
*
|
||||
*/
|
||||
static void __init mpc836x_mds_setup_arch(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
u8 __iomem *bcsr_regs = NULL;
|
||||
|
||||
if (ppc_md.progress)
|
||||
ppc_md.progress("mpc836x_mds_setup_arch()", 0);
|
||||
|
||||
/* Map BCSR area */
|
||||
np = of_find_node_by_name(NULL, "bcsr");
|
||||
if (np) {
|
||||
struct resource res;
|
||||
|
||||
of_address_to_resource(np, 0, &res);
|
||||
bcsr_regs = ioremap(res.start, resource_size(&res));
|
||||
of_node_put(np);
|
||||
}
|
||||
|
||||
mpc83xx_setup_pci();
|
||||
|
||||
#ifdef CONFIG_QUICC_ENGINE
|
||||
qe_reset();
|
||||
|
||||
if ((np = of_find_node_by_name(NULL, "par_io")) != NULL) {
|
||||
par_io_init(np);
|
||||
of_node_put(np);
|
||||
|
||||
for (np = NULL; (np = of_find_node_by_name(np, "ucc")) != NULL;)
|
||||
par_io_of_config(np);
|
||||
#ifdef CONFIG_QE_USB
|
||||
/* Must fixup Par IO before QE GPIO chips are registered. */
|
||||
par_io_config_pin(1, 2, 1, 0, 3, 0); /* USBOE */
|
||||
par_io_config_pin(1, 3, 1, 0, 3, 0); /* USBTP */
|
||||
par_io_config_pin(1, 8, 1, 0, 1, 0); /* USBTN */
|
||||
par_io_config_pin(1, 10, 2, 0, 3, 0); /* USBRXD */
|
||||
par_io_config_pin(1, 9, 2, 1, 3, 0); /* USBRP */
|
||||
par_io_config_pin(1, 11, 2, 1, 3, 0); /* USBRN */
|
||||
par_io_config_pin(2, 20, 2, 0, 1, 0); /* CLK21 */
|
||||
#endif /* CONFIG_QE_USB */
|
||||
}
|
||||
|
||||
if ((np = of_find_compatible_node(NULL, "network", "ucc_geth"))
|
||||
!= NULL){
|
||||
uint svid;
|
||||
|
||||
/* Reset the Ethernet PHY */
|
||||
#define BCSR9_GETHRST 0x20
|
||||
clrbits8(&bcsr_regs[9], BCSR9_GETHRST);
|
||||
udelay(1000);
|
||||
setbits8(&bcsr_regs[9], BCSR9_GETHRST);
|
||||
|
||||
/* handle mpc8360ea rev.2.1 erratum 2: RGMII Timing */
|
||||
svid = mfspr(SPRN_SVR);
|
||||
if (svid == 0x80480021) {
|
||||
void __iomem *immap;
|
||||
|
||||
immap = ioremap(get_immrbase() + 0x14a8, 8);
|
||||
|
||||
/*
|
||||
* IMMR + 0x14A8[4:5] = 11 (clk delay for UCC 2)
|
||||
* IMMR + 0x14A8[18:19] = 11 (clk delay for UCC 1)
|
||||
*/
|
||||
setbits32(immap, 0x0c003000);
|
||||
|
||||
/*
|
||||
* IMMR + 0x14AC[20:27] = 10101010
|
||||
* (data delay for both UCC's)
|
||||
*/
|
||||
clrsetbits_be32(immap + 4, 0xff0, 0xaa0);
|
||||
|
||||
iounmap(immap);
|
||||
}
|
||||
|
||||
iounmap(bcsr_regs);
|
||||
of_node_put(np);
|
||||
}
|
||||
#endif /* CONFIG_QUICC_ENGINE */
|
||||
}
|
||||
|
||||
machine_device_initcall(mpc836x_mds, mpc83xx_declare_of_platform_devices);
|
||||
|
||||
#ifdef CONFIG_QE_USB
|
||||
static int __init mpc836x_usb_cfg(void)
|
||||
{
|
||||
u8 __iomem *bcsr;
|
||||
struct device_node *np;
|
||||
const char *mode;
|
||||
int ret = 0;
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "fsl,mpc8360mds-bcsr");
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
bcsr = of_iomap(np, 0);
|
||||
of_node_put(np);
|
||||
if (!bcsr)
|
||||
return -ENOMEM;
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "fsl,mpc8323-qe-usb");
|
||||
if (!np) {
|
||||
ret = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
|
||||
#define BCSR8_TSEC1M_MASK (0x3 << 6)
|
||||
#define BCSR8_TSEC1M_RGMII (0x0 << 6)
|
||||
#define BCSR8_TSEC2M_MASK (0x3 << 4)
|
||||
#define BCSR8_TSEC2M_RGMII (0x0 << 4)
|
||||
/*
|
||||
* Default is GMII (2), but we should set it to RGMII (0) if we use
|
||||
* USB (Eth PHY is in RGMII mode anyway).
|
||||
*/
|
||||
clrsetbits_8(&bcsr[8], BCSR8_TSEC1M_MASK | BCSR8_TSEC2M_MASK,
|
||||
BCSR8_TSEC1M_RGMII | BCSR8_TSEC2M_RGMII);
|
||||
|
||||
#define BCSR13_USBMASK 0x0f
|
||||
#define BCSR13_nUSBEN 0x08 /* 1 - Disable, 0 - Enable */
|
||||
#define BCSR13_USBSPEED 0x04 /* 1 - Full, 0 - Low */
|
||||
#define BCSR13_USBMODE 0x02 /* 1 - Host, 0 - Function */
|
||||
#define BCSR13_nUSBVCC 0x01 /* 1 - gets VBUS, 0 - supplies VBUS */
|
||||
|
||||
clrsetbits_8(&bcsr[13], BCSR13_USBMASK, BCSR13_USBSPEED);
|
||||
|
||||
mode = of_get_property(np, "mode", NULL);
|
||||
if (mode && !strcmp(mode, "peripheral")) {
|
||||
setbits8(&bcsr[13], BCSR13_nUSBVCC);
|
||||
qe_usb_clock_set(QE_CLK21, 48000000);
|
||||
} else {
|
||||
setbits8(&bcsr[13], BCSR13_USBMODE);
|
||||
/*
|
||||
* The BCSR GPIOs are used to control power and
|
||||
* speed of the USB transceiver. This is needed for
|
||||
* the USB Host only.
|
||||
*/
|
||||
simple_gpiochip_init("fsl,mpc8360mds-bcsr-gpio");
|
||||
}
|
||||
|
||||
of_node_put(np);
|
||||
err:
|
||||
iounmap(bcsr);
|
||||
return ret;
|
||||
}
|
||||
machine_arch_initcall(mpc836x_mds, mpc836x_usb_cfg);
|
||||
#endif /* CONFIG_QE_USB */
|
||||
|
||||
/*
|
||||
* Called very early, MMU is off, device-tree isn't unflattened
|
||||
*/
|
||||
static int __init mpc836x_mds_probe(void)
|
||||
{
|
||||
unsigned long root = of_get_flat_dt_root();
|
||||
|
||||
return of_flat_dt_is_compatible(root, "MPC836xMDS");
|
||||
}
|
||||
|
||||
define_machine(mpc836x_mds) {
|
||||
.name = "MPC836x MDS",
|
||||
.probe = mpc836x_mds_probe,
|
||||
.setup_arch = mpc836x_mds_setup_arch,
|
||||
.init_IRQ = mpc83xx_ipic_and_qe_init_IRQ,
|
||||
.get_irq = ipic_get_irq,
|
||||
.restart = mpc83xx_restart,
|
||||
.time_init = mpc83xx_time_init,
|
||||
.calibrate_decr = generic_calibrate_decr,
|
||||
.progress = udbg_progress,
|
||||
};
|
||||
63
arch/powerpc/platforms/83xx/mpc836x_rdk.c
Normal file
63
arch/powerpc/platforms/83xx/mpc836x_rdk.c
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* MPC8360E-RDK board file.
|
||||
*
|
||||
* Copyright (c) 2006 Freescale Semiconductor, Inc.
|
||||
* Copyright (c) 2007-2008 MontaVista Software, Inc.
|
||||
*
|
||||
* Author: Anton Vorontsov <avorontsov@ru.mvista.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/ipic.h>
|
||||
#include <asm/udbg.h>
|
||||
#include <asm/qe.h>
|
||||
#include <asm/qe_ic.h>
|
||||
#include <sysdev/fsl_soc.h>
|
||||
#include <sysdev/fsl_pci.h>
|
||||
|
||||
#include "mpc83xx.h"
|
||||
|
||||
machine_device_initcall(mpc836x_rdk, mpc83xx_declare_of_platform_devices);
|
||||
|
||||
static void __init mpc836x_rdk_setup_arch(void)
|
||||
{
|
||||
if (ppc_md.progress)
|
||||
ppc_md.progress("mpc836x_rdk_setup_arch()", 0);
|
||||
|
||||
mpc83xx_setup_pci();
|
||||
#ifdef CONFIG_QUICC_ENGINE
|
||||
qe_reset();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Called very early, MMU is off, device-tree isn't unflattened.
|
||||
*/
|
||||
static int __init mpc836x_rdk_probe(void)
|
||||
{
|
||||
unsigned long root = of_get_flat_dt_root();
|
||||
|
||||
return of_flat_dt_is_compatible(root, "fsl,mpc8360rdk");
|
||||
}
|
||||
|
||||
define_machine(mpc836x_rdk) {
|
||||
.name = "MPC836x RDK",
|
||||
.probe = mpc836x_rdk_probe,
|
||||
.setup_arch = mpc836x_rdk_setup_arch,
|
||||
.init_IRQ = mpc83xx_ipic_and_qe_init_IRQ,
|
||||
.get_irq = ipic_get_irq,
|
||||
.restart = mpc83xx_restart,
|
||||
.time_init = mpc83xx_time_init,
|
||||
.calibrate_decr = generic_calibrate_decr,
|
||||
.progress = udbg_progress,
|
||||
};
|
||||
111
arch/powerpc/platforms/83xx/mpc837x_mds.c
Normal file
111
arch/powerpc/platforms/83xx/mpc837x_mds.c
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* arch/powerpc/platforms/83xx/mpc837x_mds.c
|
||||
*
|
||||
* Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
|
||||
*
|
||||
* MPC837x MDS board specific routines
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
||||
#include <asm/time.h>
|
||||
#include <asm/ipic.h>
|
||||
#include <asm/udbg.h>
|
||||
#include <asm/prom.h>
|
||||
#include <sysdev/fsl_pci.h>
|
||||
|
||||
#include "mpc83xx.h"
|
||||
|
||||
#define BCSR12_USB_SER_MASK 0x8a
|
||||
#define BCSR12_USB_SER_PIN 0x80
|
||||
#define BCSR12_USB_SER_DEVICE 0x02
|
||||
|
||||
static int mpc837xmds_usb_cfg(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
const void *phy_type, *mode;
|
||||
void __iomem *bcsr_regs = NULL;
|
||||
u8 bcsr12;
|
||||
int ret;
|
||||
|
||||
ret = mpc837x_usb_cfg();
|
||||
if (ret)
|
||||
return ret;
|
||||
/* Map BCSR area */
|
||||
np = of_find_compatible_node(NULL, NULL, "fsl,mpc837xmds-bcsr");
|
||||
if (np) {
|
||||
bcsr_regs = of_iomap(np, 0);
|
||||
of_node_put(np);
|
||||
}
|
||||
if (!bcsr_regs)
|
||||
return -1;
|
||||
|
||||
np = of_find_node_by_name(NULL, "usb");
|
||||
if (!np) {
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
phy_type = of_get_property(np, "phy_type", NULL);
|
||||
if (phy_type && !strcmp(phy_type, "ulpi")) {
|
||||
clrbits8(bcsr_regs + 12, BCSR12_USB_SER_PIN);
|
||||
} else if (phy_type && !strcmp(phy_type, "serial")) {
|
||||
mode = of_get_property(np, "dr_mode", NULL);
|
||||
bcsr12 = in_8(bcsr_regs + 12) & ~BCSR12_USB_SER_MASK;
|
||||
bcsr12 |= BCSR12_USB_SER_PIN;
|
||||
if (mode && !strcmp(mode, "peripheral"))
|
||||
bcsr12 |= BCSR12_USB_SER_DEVICE;
|
||||
out_8(bcsr_regs + 12, bcsr12);
|
||||
} else {
|
||||
printk(KERN_ERR "USB DR: unsupported PHY\n");
|
||||
}
|
||||
|
||||
of_node_put(np);
|
||||
out:
|
||||
iounmap(bcsr_regs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ************************************************************************
|
||||
*
|
||||
* Setup the architecture
|
||||
*
|
||||
*/
|
||||
static void __init mpc837x_mds_setup_arch(void)
|
||||
{
|
||||
if (ppc_md.progress)
|
||||
ppc_md.progress("mpc837x_mds_setup_arch()", 0);
|
||||
|
||||
mpc83xx_setup_pci();
|
||||
mpc837xmds_usb_cfg();
|
||||
}
|
||||
|
||||
machine_device_initcall(mpc837x_mds, mpc83xx_declare_of_platform_devices);
|
||||
|
||||
/*
|
||||
* Called very early, MMU is off, device-tree isn't unflattened
|
||||
*/
|
||||
static int __init mpc837x_mds_probe(void)
|
||||
{
|
||||
unsigned long root = of_get_flat_dt_root();
|
||||
|
||||
return of_flat_dt_is_compatible(root, "fsl,mpc837xmds");
|
||||
}
|
||||
|
||||
define_machine(mpc837x_mds) {
|
||||
.name = "MPC837x MDS",
|
||||
.probe = mpc837x_mds_probe,
|
||||
.setup_arch = mpc837x_mds_setup_arch,
|
||||
.init_IRQ = mpc83xx_ipic_init_IRQ,
|
||||
.get_irq = ipic_get_irq,
|
||||
.restart = mpc83xx_restart,
|
||||
.time_init = mpc83xx_time_init,
|
||||
.calibrate_decr = generic_calibrate_decr,
|
||||
.progress = udbg_progress,
|
||||
};
|
||||
89
arch/powerpc/platforms/83xx/mpc837x_rdb.c
Normal file
89
arch/powerpc/platforms/83xx/mpc837x_rdb.c
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* arch/powerpc/platforms/83xx/mpc837x_rdb.c
|
||||
*
|
||||
* Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
|
||||
*
|
||||
* MPC837x RDB board specific routines
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
||||
#include <asm/time.h>
|
||||
#include <asm/ipic.h>
|
||||
#include <asm/udbg.h>
|
||||
#include <sysdev/fsl_soc.h>
|
||||
#include <sysdev/fsl_pci.h>
|
||||
|
||||
#include "mpc83xx.h"
|
||||
|
||||
static void mpc837x_rdb_sd_cfg(void)
|
||||
{
|
||||
void __iomem *im;
|
||||
|
||||
im = ioremap(get_immrbase(), 0x1000);
|
||||
if (!im) {
|
||||
WARN_ON(1);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* On RDB boards (in contrast to MDS) USBB pins are used for SD only,
|
||||
* so we can safely mux them away from the USB block.
|
||||
*/
|
||||
clrsetbits_be32(im + MPC83XX_SICRL_OFFS, MPC837X_SICRL_USBB_MASK,
|
||||
MPC837X_SICRL_SD);
|
||||
clrsetbits_be32(im + MPC83XX_SICRH_OFFS, MPC837X_SICRH_SPI_MASK,
|
||||
MPC837X_SICRH_SD);
|
||||
iounmap(im);
|
||||
}
|
||||
|
||||
/* ************************************************************************
|
||||
*
|
||||
* Setup the architecture
|
||||
*
|
||||
*/
|
||||
static void __init mpc837x_rdb_setup_arch(void)
|
||||
{
|
||||
if (ppc_md.progress)
|
||||
ppc_md.progress("mpc837x_rdb_setup_arch()", 0);
|
||||
|
||||
mpc83xx_setup_pci();
|
||||
mpc837x_usb_cfg();
|
||||
mpc837x_rdb_sd_cfg();
|
||||
}
|
||||
|
||||
machine_device_initcall(mpc837x_rdb, mpc83xx_declare_of_platform_devices);
|
||||
|
||||
static const char * const board[] __initconst = {
|
||||
"fsl,mpc8377rdb",
|
||||
"fsl,mpc8378rdb",
|
||||
"fsl,mpc8379rdb",
|
||||
"fsl,mpc8377wlan",
|
||||
NULL
|
||||
};
|
||||
|
||||
/*
|
||||
* Called very early, MMU is off, device-tree isn't unflattened
|
||||
*/
|
||||
static int __init mpc837x_rdb_probe(void)
|
||||
{
|
||||
return of_flat_dt_match(of_get_flat_dt_root(), board);
|
||||
}
|
||||
|
||||
define_machine(mpc837x_rdb) {
|
||||
.name = "MPC837x RDB/WLAN",
|
||||
.probe = mpc837x_rdb_probe,
|
||||
.setup_arch = mpc837x_rdb_setup_arch,
|
||||
.init_IRQ = mpc83xx_ipic_init_IRQ,
|
||||
.get_irq = ipic_get_irq,
|
||||
.restart = mpc83xx_restart,
|
||||
.time_init = mpc83xx_time_init,
|
||||
.calibrate_decr = generic_calibrate_decr,
|
||||
.progress = udbg_progress,
|
||||
};
|
||||
90
arch/powerpc/platforms/83xx/mpc83xx.h
Normal file
90
arch/powerpc/platforms/83xx/mpc83xx.h
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
#ifndef __MPC83XX_H__
|
||||
#define __MPC83XX_H__
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <asm/pci-bridge.h>
|
||||
|
||||
/* System Clock Control Register */
|
||||
#define MPC83XX_SCCR_OFFS 0xA08
|
||||
#define MPC83XX_SCCR_USB_MASK 0x00f00000
|
||||
#define MPC83XX_SCCR_USB_MPHCM_11 0x00c00000
|
||||
#define MPC83XX_SCCR_USB_MPHCM_01 0x00400000
|
||||
#define MPC83XX_SCCR_USB_MPHCM_10 0x00800000
|
||||
#define MPC83XX_SCCR_USB_DRCM_11 0x00300000
|
||||
#define MPC83XX_SCCR_USB_DRCM_01 0x00100000
|
||||
#define MPC83XX_SCCR_USB_DRCM_10 0x00200000
|
||||
#define MPC8315_SCCR_USB_MASK 0x00c00000
|
||||
#define MPC8315_SCCR_USB_DRCM_11 0x00c00000
|
||||
#define MPC8315_SCCR_USB_DRCM_01 0x00400000
|
||||
#define MPC837X_SCCR_USB_DRCM_11 0x00c00000
|
||||
|
||||
/* system i/o configuration register low */
|
||||
#define MPC83XX_SICRL_OFFS 0x114
|
||||
#define MPC834X_SICRL_USB_MASK 0x60000000
|
||||
#define MPC834X_SICRL_USB0 0x20000000
|
||||
#define MPC834X_SICRL_USB1 0x40000000
|
||||
#define MPC831X_SICRL_USB_MASK 0x00000c00
|
||||
#define MPC831X_SICRL_USB_ULPI 0x00000800
|
||||
#define MPC8315_SICRL_USB_MASK 0x000000fc
|
||||
#define MPC8315_SICRL_USB_ULPI 0x00000054
|
||||
#define MPC837X_SICRL_USB_MASK 0xf0000000
|
||||
#define MPC837X_SICRL_USB_ULPI 0x50000000
|
||||
#define MPC837X_SICRL_USBB_MASK 0x30000000
|
||||
#define MPC837X_SICRL_SD 0x20000000
|
||||
|
||||
/* system i/o configuration register high */
|
||||
#define MPC83XX_SICRH_OFFS 0x118
|
||||
#define MPC8308_SICRH_USB_MASK 0x000c0000
|
||||
#define MPC8308_SICRH_USB_ULPI 0x00040000
|
||||
#define MPC834X_SICRH_USB_UTMI 0x00020000
|
||||
#define MPC831X_SICRH_USB_MASK 0x000000e0
|
||||
#define MPC831X_SICRH_USB_ULPI 0x000000a0
|
||||
#define MPC8315_SICRH_USB_MASK 0x0000ff00
|
||||
#define MPC8315_SICRH_USB_ULPI 0x00000000
|
||||
#define MPC837X_SICRH_SPI_MASK 0x00000003
|
||||
#define MPC837X_SICRH_SD 0x00000001
|
||||
|
||||
/* USB Control Register */
|
||||
#define FSL_USB2_CONTROL_OFFS 0x500
|
||||
#define CONTROL_UTMI_PHY_EN 0x00000200
|
||||
#define CONTROL_REFSEL_24MHZ 0x00000040
|
||||
#define CONTROL_REFSEL_48MHZ 0x00000080
|
||||
#define CONTROL_PHY_CLK_SEL_ULPI 0x00000400
|
||||
#define CONTROL_OTG_PORT 0x00000020
|
||||
|
||||
/* USB PORTSC Registers */
|
||||
#define FSL_USB2_PORTSC1_OFFS 0x184
|
||||
#define FSL_USB2_PORTSC2_OFFS 0x188
|
||||
#define PORTSCX_PTW_16BIT 0x10000000
|
||||
#define PORTSCX_PTS_UTMI 0x00000000
|
||||
#define PORTSCX_PTS_ULPI 0x80000000
|
||||
|
||||
/*
|
||||
* Declaration for the various functions exported by the
|
||||
* mpc83xx_* files. Mostly for use by mpc83xx_setup
|
||||
*/
|
||||
|
||||
extern void mpc83xx_restart(char *cmd);
|
||||
extern long mpc83xx_time_init(void);
|
||||
extern int mpc837x_usb_cfg(void);
|
||||
extern int mpc834x_usb_cfg(void);
|
||||
extern int mpc831x_usb_cfg(void);
|
||||
extern void mpc83xx_ipic_init_IRQ(void);
|
||||
#ifdef CONFIG_QUICC_ENGINE
|
||||
extern void mpc83xx_qe_init_IRQ(void);
|
||||
extern void mpc83xx_ipic_and_qe_init_IRQ(void);
|
||||
#else
|
||||
static inline void __init mpc83xx_qe_init_IRQ(void) {}
|
||||
#define mpc83xx_ipic_and_qe_init_IRQ mpc83xx_ipic_init_IRQ
|
||||
#endif /* CONFIG_QUICC_ENGINE */
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
extern void mpc83xx_setup_pci(void);
|
||||
#else
|
||||
#define mpc83xx_setup_pci() do {} while (0)
|
||||
#endif
|
||||
|
||||
extern int mpc83xx_declare_of_platform_devices(void);
|
||||
|
||||
#endif /* __MPC83XX_H__ */
|
||||
78
arch/powerpc/platforms/83xx/sbc834x.c
Normal file
78
arch/powerpc/platforms/83xx/sbc834x.c
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* arch/powerpc/platforms/83xx/sbc834x.c
|
||||
*
|
||||
* Wind River SBC834x board specific routines
|
||||
*
|
||||
* By Paul Gortmaker (see MAINTAINERS for contact information)
|
||||
*
|
||||
* Based largely on the mpc834x_mds.c support by Kumar Gala.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/root_dev.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
||||
#include <linux/atomic.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/ipic.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/udbg.h>
|
||||
#include <sysdev/fsl_soc.h>
|
||||
#include <sysdev/fsl_pci.h>
|
||||
|
||||
#include "mpc83xx.h"
|
||||
|
||||
/* ************************************************************************
|
||||
*
|
||||
* Setup the architecture
|
||||
*
|
||||
*/
|
||||
static void __init sbc834x_setup_arch(void)
|
||||
{
|
||||
if (ppc_md.progress)
|
||||
ppc_md.progress("sbc834x_setup_arch()", 0);
|
||||
|
||||
mpc83xx_setup_pci();
|
||||
}
|
||||
|
||||
machine_device_initcall(sbc834x, mpc83xx_declare_of_platform_devices);
|
||||
|
||||
/*
|
||||
* Called very early, MMU is off, device-tree isn't unflattened
|
||||
*/
|
||||
static int __init sbc834x_probe(void)
|
||||
{
|
||||
unsigned long root = of_get_flat_dt_root();
|
||||
|
||||
return of_flat_dt_is_compatible(root, "SBC834xE");
|
||||
}
|
||||
|
||||
define_machine(sbc834x) {
|
||||
.name = "SBC834xE",
|
||||
.probe = sbc834x_probe,
|
||||
.setup_arch = sbc834x_setup_arch,
|
||||
.init_IRQ = mpc83xx_ipic_init_IRQ,
|
||||
.get_irq = ipic_get_irq,
|
||||
.restart = mpc83xx_restart,
|
||||
.time_init = mpc83xx_time_init,
|
||||
.calibrate_decr = generic_calibrate_decr,
|
||||
.progress = udbg_progress,
|
||||
};
|
||||
533
arch/powerpc/platforms/83xx/suspend-asm.S
Normal file
533
arch/powerpc/platforms/83xx/suspend-asm.S
Normal file
|
|
@ -0,0 +1,533 @@
|
|||
/*
|
||||
* Enter and leave deep sleep state on MPC83xx
|
||||
*
|
||||
* Copyright (c) 2006-2008 Freescale Semiconductor, Inc.
|
||||
* Author: Scott Wood <scottwood@freescale.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published
|
||||
* by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <asm/page.h>
|
||||
#include <asm/ppc_asm.h>
|
||||
#include <asm/reg.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
|
||||
#define SS_MEMSAVE 0x00 /* First 8 bytes of RAM */
|
||||
#define SS_HID 0x08 /* 3 HIDs */
|
||||
#define SS_IABR 0x14 /* 2 IABRs */
|
||||
#define SS_IBCR 0x1c
|
||||
#define SS_DABR 0x20 /* 2 DABRs */
|
||||
#define SS_DBCR 0x28
|
||||
#define SS_SP 0x2c
|
||||
#define SS_SR 0x30 /* 16 segment registers */
|
||||
#define SS_R2 0x70
|
||||
#define SS_MSR 0x74
|
||||
#define SS_SDR1 0x78
|
||||
#define SS_LR 0x7c
|
||||
#define SS_SPRG 0x80 /* 4 SPRGs */
|
||||
#define SS_DBAT 0x90 /* 8 DBATs */
|
||||
#define SS_IBAT 0xd0 /* 8 IBATs */
|
||||
#define SS_TB 0x110
|
||||
#define SS_CR 0x118
|
||||
#define SS_GPREG 0x11c /* r12-r31 */
|
||||
#define STATE_SAVE_SIZE 0x16c
|
||||
|
||||
.section .data
|
||||
.align 5
|
||||
|
||||
mpc83xx_sleep_save_area:
|
||||
.space STATE_SAVE_SIZE
|
||||
immrbase:
|
||||
.long 0
|
||||
|
||||
.section .text
|
||||
.align 5
|
||||
|
||||
/* r3 = physical address of IMMR */
|
||||
_GLOBAL(mpc83xx_enter_deep_sleep)
|
||||
lis r4, immrbase@ha
|
||||
stw r3, immrbase@l(r4)
|
||||
|
||||
/* The first 2 words of memory are used to communicate with the
|
||||
* bootloader, to tell it how to resume.
|
||||
*
|
||||
* The first word is the magic number 0xf5153ae5, and the second
|
||||
* is the pointer to mpc83xx_deep_resume.
|
||||
*
|
||||
* The original content of these two words is saved in SS_MEMSAVE.
|
||||
*/
|
||||
|
||||
lis r3, mpc83xx_sleep_save_area@h
|
||||
ori r3, r3, mpc83xx_sleep_save_area@l
|
||||
|
||||
lis r4, KERNELBASE@h
|
||||
lwz r5, 0(r4)
|
||||
lwz r6, 4(r4)
|
||||
|
||||
stw r5, SS_MEMSAVE+0(r3)
|
||||
stw r6, SS_MEMSAVE+4(r3)
|
||||
|
||||
mfspr r5, SPRN_HID0
|
||||
mfspr r6, SPRN_HID1
|
||||
mfspr r7, SPRN_HID2
|
||||
|
||||
stw r5, SS_HID+0(r3)
|
||||
stw r6, SS_HID+4(r3)
|
||||
stw r7, SS_HID+8(r3)
|
||||
|
||||
mfspr r4, SPRN_IABR
|
||||
mfspr r5, SPRN_IABR2
|
||||
mfspr r6, SPRN_IBCR
|
||||
mfspr r7, SPRN_DABR
|
||||
mfspr r8, SPRN_DABR2
|
||||
mfspr r9, SPRN_DBCR
|
||||
|
||||
stw r4, SS_IABR+0(r3)
|
||||
stw r5, SS_IABR+4(r3)
|
||||
stw r6, SS_IBCR(r3)
|
||||
stw r7, SS_DABR+0(r3)
|
||||
stw r8, SS_DABR+4(r3)
|
||||
stw r9, SS_DBCR(r3)
|
||||
|
||||
mfspr r4, SPRN_SPRG0
|
||||
mfspr r5, SPRN_SPRG1
|
||||
mfspr r6, SPRN_SPRG2
|
||||
mfspr r7, SPRN_SPRG3
|
||||
mfsdr1 r8
|
||||
|
||||
stw r4, SS_SPRG+0(r3)
|
||||
stw r5, SS_SPRG+4(r3)
|
||||
stw r6, SS_SPRG+8(r3)
|
||||
stw r7, SS_SPRG+12(r3)
|
||||
stw r8, SS_SDR1(r3)
|
||||
|
||||
mfspr r4, SPRN_DBAT0U
|
||||
mfspr r5, SPRN_DBAT0L
|
||||
mfspr r6, SPRN_DBAT1U
|
||||
mfspr r7, SPRN_DBAT1L
|
||||
|
||||
stw r4, SS_DBAT+0x00(r3)
|
||||
stw r5, SS_DBAT+0x04(r3)
|
||||
stw r6, SS_DBAT+0x08(r3)
|
||||
stw r7, SS_DBAT+0x0c(r3)
|
||||
|
||||
mfspr r4, SPRN_DBAT2U
|
||||
mfspr r5, SPRN_DBAT2L
|
||||
mfspr r6, SPRN_DBAT3U
|
||||
mfspr r7, SPRN_DBAT3L
|
||||
|
||||
stw r4, SS_DBAT+0x10(r3)
|
||||
stw r5, SS_DBAT+0x14(r3)
|
||||
stw r6, SS_DBAT+0x18(r3)
|
||||
stw r7, SS_DBAT+0x1c(r3)
|
||||
|
||||
mfspr r4, SPRN_DBAT4U
|
||||
mfspr r5, SPRN_DBAT4L
|
||||
mfspr r6, SPRN_DBAT5U
|
||||
mfspr r7, SPRN_DBAT5L
|
||||
|
||||
stw r4, SS_DBAT+0x20(r3)
|
||||
stw r5, SS_DBAT+0x24(r3)
|
||||
stw r6, SS_DBAT+0x28(r3)
|
||||
stw r7, SS_DBAT+0x2c(r3)
|
||||
|
||||
mfspr r4, SPRN_DBAT6U
|
||||
mfspr r5, SPRN_DBAT6L
|
||||
mfspr r6, SPRN_DBAT7U
|
||||
mfspr r7, SPRN_DBAT7L
|
||||
|
||||
stw r4, SS_DBAT+0x30(r3)
|
||||
stw r5, SS_DBAT+0x34(r3)
|
||||
stw r6, SS_DBAT+0x38(r3)
|
||||
stw r7, SS_DBAT+0x3c(r3)
|
||||
|
||||
mfspr r4, SPRN_IBAT0U
|
||||
mfspr r5, SPRN_IBAT0L
|
||||
mfspr r6, SPRN_IBAT1U
|
||||
mfspr r7, SPRN_IBAT1L
|
||||
|
||||
stw r4, SS_IBAT+0x00(r3)
|
||||
stw r5, SS_IBAT+0x04(r3)
|
||||
stw r6, SS_IBAT+0x08(r3)
|
||||
stw r7, SS_IBAT+0x0c(r3)
|
||||
|
||||
mfspr r4, SPRN_IBAT2U
|
||||
mfspr r5, SPRN_IBAT2L
|
||||
mfspr r6, SPRN_IBAT3U
|
||||
mfspr r7, SPRN_IBAT3L
|
||||
|
||||
stw r4, SS_IBAT+0x10(r3)
|
||||
stw r5, SS_IBAT+0x14(r3)
|
||||
stw r6, SS_IBAT+0x18(r3)
|
||||
stw r7, SS_IBAT+0x1c(r3)
|
||||
|
||||
mfspr r4, SPRN_IBAT4U
|
||||
mfspr r5, SPRN_IBAT4L
|
||||
mfspr r6, SPRN_IBAT5U
|
||||
mfspr r7, SPRN_IBAT5L
|
||||
|
||||
stw r4, SS_IBAT+0x20(r3)
|
||||
stw r5, SS_IBAT+0x24(r3)
|
||||
stw r6, SS_IBAT+0x28(r3)
|
||||
stw r7, SS_IBAT+0x2c(r3)
|
||||
|
||||
mfspr r4, SPRN_IBAT6U
|
||||
mfspr r5, SPRN_IBAT6L
|
||||
mfspr r6, SPRN_IBAT7U
|
||||
mfspr r7, SPRN_IBAT7L
|
||||
|
||||
stw r4, SS_IBAT+0x30(r3)
|
||||
stw r5, SS_IBAT+0x34(r3)
|
||||
stw r6, SS_IBAT+0x38(r3)
|
||||
stw r7, SS_IBAT+0x3c(r3)
|
||||
|
||||
mfmsr r4
|
||||
mflr r5
|
||||
mfcr r6
|
||||
|
||||
stw r4, SS_MSR(r3)
|
||||
stw r5, SS_LR(r3)
|
||||
stw r6, SS_CR(r3)
|
||||
stw r1, SS_SP(r3)
|
||||
stw r2, SS_R2(r3)
|
||||
|
||||
1: mftbu r4
|
||||
mftb r5
|
||||
mftbu r6
|
||||
cmpw r4, r6
|
||||
bne 1b
|
||||
|
||||
stw r4, SS_TB+0(r3)
|
||||
stw r5, SS_TB+4(r3)
|
||||
|
||||
stmw r12, SS_GPREG(r3)
|
||||
|
||||
li r4, 0
|
||||
addi r6, r3, SS_SR-4
|
||||
1: mfsrin r5, r4
|
||||
stwu r5, 4(r6)
|
||||
addis r4, r4, 0x1000
|
||||
cmpwi r4, 0
|
||||
bne 1b
|
||||
|
||||
/* Disable machine checks and critical exceptions */
|
||||
mfmsr r4
|
||||
rlwinm r4, r4, 0, ~MSR_CE
|
||||
rlwinm r4, r4, 0, ~MSR_ME
|
||||
mtmsr r4
|
||||
isync
|
||||
|
||||
#define TMP_VIRT_IMMR 0xf0000000
|
||||
#define DEFAULT_IMMR_VALUE 0xff400000
|
||||
#define IMMRBAR_BASE 0x0000
|
||||
|
||||
lis r4, immrbase@ha
|
||||
lwz r4, immrbase@l(r4)
|
||||
|
||||
/* Use DBAT0 to address the current IMMR space */
|
||||
|
||||
ori r4, r4, 0x002a
|
||||
mtspr SPRN_DBAT0L, r4
|
||||
lis r8, TMP_VIRT_IMMR@h
|
||||
ori r4, r8, 0x001e /* 1 MByte accessible from Kernel Space only */
|
||||
mtspr SPRN_DBAT0U, r4
|
||||
isync
|
||||
|
||||
/* Use DBAT1 to address the original IMMR space */
|
||||
|
||||
lis r4, DEFAULT_IMMR_VALUE@h
|
||||
ori r4, r4, 0x002a
|
||||
mtspr SPRN_DBAT1L, r4
|
||||
lis r9, (TMP_VIRT_IMMR + 0x01000000)@h
|
||||
ori r4, r9, 0x001e /* 1 MByte accessible from Kernel Space only */
|
||||
mtspr SPRN_DBAT1U, r4
|
||||
isync
|
||||
|
||||
/* Use DBAT2 to address the beginning of RAM. This isn't done
|
||||
* using the normal virtual mapping, because with page debugging
|
||||
* enabled it will be read-only.
|
||||
*/
|
||||
|
||||
li r4, 0x0002
|
||||
mtspr SPRN_DBAT2L, r4
|
||||
lis r4, KERNELBASE@h
|
||||
ori r4, r4, 0x001e /* 1 MByte accessible from Kernel Space only */
|
||||
mtspr SPRN_DBAT2U, r4
|
||||
isync
|
||||
|
||||
/* Flush the cache with our BAT, as there will be TLB misses
|
||||
* otherwise if page debugging is enabled, and these misses
|
||||
* will disturb the PLRU algorithm.
|
||||
*/
|
||||
|
||||
bl __flush_disable_L1
|
||||
|
||||
/* Keep the i-cache enabled, so the hack below for low-boot
|
||||
* flash will work.
|
||||
*/
|
||||
mfspr r3, SPRN_HID0
|
||||
ori r3, r3, HID0_ICE
|
||||
mtspr SPRN_HID0, r3
|
||||
isync
|
||||
|
||||
lis r6, 0xf515
|
||||
ori r6, r6, 0x3ae5
|
||||
|
||||
lis r7, mpc83xx_deep_resume@h
|
||||
ori r7, r7, mpc83xx_deep_resume@l
|
||||
tophys(r7, r7)
|
||||
|
||||
lis r5, KERNELBASE@h
|
||||
stw r6, 0(r5)
|
||||
stw r7, 4(r5)
|
||||
|
||||
/* Reset BARs */
|
||||
|
||||
li r4, 0
|
||||
stw r4, 0x0024(r8)
|
||||
stw r4, 0x002c(r8)
|
||||
stw r4, 0x0034(r8)
|
||||
stw r4, 0x003c(r8)
|
||||
stw r4, 0x0064(r8)
|
||||
stw r4, 0x006c(r8)
|
||||
|
||||
/* Rev 1 of the 8313 has problems with wakeup events that are
|
||||
* pending during the transition to deep sleep state (such as if
|
||||
* the PCI host sets the state to D3 and then D0 in rapid
|
||||
* succession). This check shrinks the race window somewhat.
|
||||
*
|
||||
* See erratum PCI23, though the problem is not limited
|
||||
* to PCI.
|
||||
*/
|
||||
|
||||
lwz r3, 0x0b04(r8)
|
||||
andi. r3, r3, 1
|
||||
bne- mpc83xx_deep_resume
|
||||
|
||||
/* Move IMMR back to the default location, following the
|
||||
* procedure specified in the MPC8313 manual.
|
||||
*/
|
||||
lwz r4, IMMRBAR_BASE(r8)
|
||||
isync
|
||||
lis r4, DEFAULT_IMMR_VALUE@h
|
||||
stw r4, IMMRBAR_BASE(r8)
|
||||
lis r4, KERNELBASE@h
|
||||
lwz r4, 0(r4)
|
||||
isync
|
||||
lwz r4, IMMRBAR_BASE(r9)
|
||||
mr r8, r9
|
||||
isync
|
||||
|
||||
/* Check the Reset Configuration Word to see whether flash needs
|
||||
* to be mapped at a low address or a high address.
|
||||
*/
|
||||
|
||||
lwz r4, 0x0904(r8)
|
||||
andis. r4, r4, 0x0400
|
||||
li r4, 0
|
||||
beq boot_low
|
||||
lis r4, 0xff80
|
||||
boot_low:
|
||||
stw r4, 0x0020(r8)
|
||||
lis r7, 0x8000
|
||||
ori r7, r7, 0x0016
|
||||
|
||||
mfspr r5, SPRN_HID0
|
||||
rlwinm r5, r5, 0, ~(HID0_DOZE | HID0_NAP)
|
||||
oris r5, r5, HID0_SLEEP@h
|
||||
mtspr SPRN_HID0, r5
|
||||
isync
|
||||
|
||||
mfmsr r5
|
||||
oris r5, r5, MSR_POW@h
|
||||
|
||||
/* Enable the flash mapping at the appropriate address. This
|
||||
* mapping will override the RAM mapping if booting low, so there's
|
||||
* no need to disable the latter. This must be done inside the same
|
||||
* cache line as setting MSR_POW, so that no instruction fetches
|
||||
* from RAM happen after the flash mapping is turned on.
|
||||
*/
|
||||
|
||||
.align 5
|
||||
stw r7, 0x0024(r8)
|
||||
sync
|
||||
isync
|
||||
mtmsr r5
|
||||
isync
|
||||
1: b 1b
|
||||
|
||||
mpc83xx_deep_resume:
|
||||
lis r4, 1f@h
|
||||
ori r4, r4, 1f@l
|
||||
tophys(r4, r4)
|
||||
mtsrr0 r4
|
||||
|
||||
mfmsr r4
|
||||
rlwinm r4, r4, 0, ~(MSR_IR | MSR_DR)
|
||||
mtsrr1 r4
|
||||
|
||||
rfi
|
||||
|
||||
1: tlbia
|
||||
bl __inval_enable_L1
|
||||
|
||||
lis r3, mpc83xx_sleep_save_area@h
|
||||
ori r3, r3, mpc83xx_sleep_save_area@l
|
||||
tophys(r3, r3)
|
||||
|
||||
lwz r5, SS_MEMSAVE+0(r3)
|
||||
lwz r6, SS_MEMSAVE+4(r3)
|
||||
|
||||
stw r5, 0(0)
|
||||
stw r6, 4(0)
|
||||
|
||||
lwz r5, SS_HID+0(r3)
|
||||
lwz r6, SS_HID+4(r3)
|
||||
lwz r7, SS_HID+8(r3)
|
||||
|
||||
mtspr SPRN_HID0, r5
|
||||
mtspr SPRN_HID1, r6
|
||||
mtspr SPRN_HID2, r7
|
||||
|
||||
lwz r4, SS_IABR+0(r3)
|
||||
lwz r5, SS_IABR+4(r3)
|
||||
lwz r6, SS_IBCR(r3)
|
||||
lwz r7, SS_DABR+0(r3)
|
||||
lwz r8, SS_DABR+4(r3)
|
||||
lwz r9, SS_DBCR(r3)
|
||||
|
||||
mtspr SPRN_IABR, r4
|
||||
mtspr SPRN_IABR2, r5
|
||||
mtspr SPRN_IBCR, r6
|
||||
mtspr SPRN_DABR, r7
|
||||
mtspr SPRN_DABR2, r8
|
||||
mtspr SPRN_DBCR, r9
|
||||
|
||||
li r4, 0
|
||||
addi r6, r3, SS_SR-4
|
||||
1: lwzu r5, 4(r6)
|
||||
mtsrin r5, r4
|
||||
addis r4, r4, 0x1000
|
||||
cmpwi r4, 0
|
||||
bne 1b
|
||||
|
||||
lwz r4, SS_DBAT+0x00(r3)
|
||||
lwz r5, SS_DBAT+0x04(r3)
|
||||
lwz r6, SS_DBAT+0x08(r3)
|
||||
lwz r7, SS_DBAT+0x0c(r3)
|
||||
|
||||
mtspr SPRN_DBAT0U, r4
|
||||
mtspr SPRN_DBAT0L, r5
|
||||
mtspr SPRN_DBAT1U, r6
|
||||
mtspr SPRN_DBAT1L, r7
|
||||
|
||||
lwz r4, SS_DBAT+0x10(r3)
|
||||
lwz r5, SS_DBAT+0x14(r3)
|
||||
lwz r6, SS_DBAT+0x18(r3)
|
||||
lwz r7, SS_DBAT+0x1c(r3)
|
||||
|
||||
mtspr SPRN_DBAT2U, r4
|
||||
mtspr SPRN_DBAT2L, r5
|
||||
mtspr SPRN_DBAT3U, r6
|
||||
mtspr SPRN_DBAT3L, r7
|
||||
|
||||
lwz r4, SS_DBAT+0x20(r3)
|
||||
lwz r5, SS_DBAT+0x24(r3)
|
||||
lwz r6, SS_DBAT+0x28(r3)
|
||||
lwz r7, SS_DBAT+0x2c(r3)
|
||||
|
||||
mtspr SPRN_DBAT4U, r4
|
||||
mtspr SPRN_DBAT4L, r5
|
||||
mtspr SPRN_DBAT5U, r6
|
||||
mtspr SPRN_DBAT5L, r7
|
||||
|
||||
lwz r4, SS_DBAT+0x30(r3)
|
||||
lwz r5, SS_DBAT+0x34(r3)
|
||||
lwz r6, SS_DBAT+0x38(r3)
|
||||
lwz r7, SS_DBAT+0x3c(r3)
|
||||
|
||||
mtspr SPRN_DBAT6U, r4
|
||||
mtspr SPRN_DBAT6L, r5
|
||||
mtspr SPRN_DBAT7U, r6
|
||||
mtspr SPRN_DBAT7L, r7
|
||||
|
||||
lwz r4, SS_IBAT+0x00(r3)
|
||||
lwz r5, SS_IBAT+0x04(r3)
|
||||
lwz r6, SS_IBAT+0x08(r3)
|
||||
lwz r7, SS_IBAT+0x0c(r3)
|
||||
|
||||
mtspr SPRN_IBAT0U, r4
|
||||
mtspr SPRN_IBAT0L, r5
|
||||
mtspr SPRN_IBAT1U, r6
|
||||
mtspr SPRN_IBAT1L, r7
|
||||
|
||||
lwz r4, SS_IBAT+0x10(r3)
|
||||
lwz r5, SS_IBAT+0x14(r3)
|
||||
lwz r6, SS_IBAT+0x18(r3)
|
||||
lwz r7, SS_IBAT+0x1c(r3)
|
||||
|
||||
mtspr SPRN_IBAT2U, r4
|
||||
mtspr SPRN_IBAT2L, r5
|
||||
mtspr SPRN_IBAT3U, r6
|
||||
mtspr SPRN_IBAT3L, r7
|
||||
|
||||
lwz r4, SS_IBAT+0x20(r3)
|
||||
lwz r5, SS_IBAT+0x24(r3)
|
||||
lwz r6, SS_IBAT+0x28(r3)
|
||||
lwz r7, SS_IBAT+0x2c(r3)
|
||||
|
||||
mtspr SPRN_IBAT4U, r4
|
||||
mtspr SPRN_IBAT4L, r5
|
||||
mtspr SPRN_IBAT5U, r6
|
||||
mtspr SPRN_IBAT5L, r7
|
||||
|
||||
lwz r4, SS_IBAT+0x30(r3)
|
||||
lwz r5, SS_IBAT+0x34(r3)
|
||||
lwz r6, SS_IBAT+0x38(r3)
|
||||
lwz r7, SS_IBAT+0x3c(r3)
|
||||
|
||||
mtspr SPRN_IBAT6U, r4
|
||||
mtspr SPRN_IBAT6L, r5
|
||||
mtspr SPRN_IBAT7U, r6
|
||||
mtspr SPRN_IBAT7L, r7
|
||||
|
||||
lwz r4, SS_SPRG+0(r3)
|
||||
lwz r5, SS_SPRG+4(r3)
|
||||
lwz r6, SS_SPRG+8(r3)
|
||||
lwz r7, SS_SPRG+12(r3)
|
||||
lwz r8, SS_SDR1(r3)
|
||||
|
||||
mtspr SPRN_SPRG0, r4
|
||||
mtspr SPRN_SPRG1, r5
|
||||
mtspr SPRN_SPRG2, r6
|
||||
mtspr SPRN_SPRG3, r7
|
||||
mtsdr1 r8
|
||||
|
||||
lwz r4, SS_MSR(r3)
|
||||
lwz r5, SS_LR(r3)
|
||||
lwz r6, SS_CR(r3)
|
||||
lwz r1, SS_SP(r3)
|
||||
lwz r2, SS_R2(r3)
|
||||
|
||||
mtsrr1 r4
|
||||
mtsrr0 r5
|
||||
mtcr r6
|
||||
|
||||
li r4, 0
|
||||
mtspr SPRN_TBWL, r4
|
||||
|
||||
lwz r4, SS_TB+0(r3)
|
||||
lwz r5, SS_TB+4(r3)
|
||||
|
||||
mtspr SPRN_TBWU, r4
|
||||
mtspr SPRN_TBWL, r5
|
||||
|
||||
lmw r12, SS_GPREG(r3)
|
||||
|
||||
/* Kick decrementer */
|
||||
li r0, 1
|
||||
mtdec r0
|
||||
|
||||
rfi
|
||||
450
arch/powerpc/platforms/83xx/suspend.c
Normal file
450
arch/powerpc/platforms/83xx/suspend.c
Normal file
|
|
@ -0,0 +1,450 @@
|
|||
/*
|
||||
* MPC83xx suspend support
|
||||
*
|
||||
* Author: Scott Wood <scottwood@freescale.com>
|
||||
*
|
||||
* Copyright (c) 2006-2007 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published
|
||||
* by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/pm.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/fsl_devices.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/export.h>
|
||||
|
||||
#include <asm/reg.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/mpc6xx.h>
|
||||
#include <asm/switch_to.h>
|
||||
|
||||
#include <sysdev/fsl_soc.h>
|
||||
|
||||
#define PMCCR1_NEXT_STATE 0x0C /* Next state for power management */
|
||||
#define PMCCR1_NEXT_STATE_SHIFT 2
|
||||
#define PMCCR1_CURR_STATE 0x03 /* Current state for power management*/
|
||||
#define IMMR_SYSCR_OFFSET 0x100
|
||||
#define IMMR_RCW_OFFSET 0x900
|
||||
#define RCW_PCI_HOST 0x80000000
|
||||
|
||||
void mpc83xx_enter_deep_sleep(phys_addr_t immrbase);
|
||||
|
||||
struct mpc83xx_pmc {
|
||||
u32 config;
|
||||
#define PMCCR_DLPEN 2 /* DDR SDRAM low power enable */
|
||||
#define PMCCR_SLPEN 1 /* System low power enable */
|
||||
|
||||
u32 event;
|
||||
u32 mask;
|
||||
/* All but PMCI are deep-sleep only */
|
||||
#define PMCER_GPIO 0x100
|
||||
#define PMCER_PCI 0x080
|
||||
#define PMCER_USB 0x040
|
||||
#define PMCER_ETSEC1 0x020
|
||||
#define PMCER_ETSEC2 0x010
|
||||
#define PMCER_TIMER 0x008
|
||||
#define PMCER_INT1 0x004
|
||||
#define PMCER_INT2 0x002
|
||||
#define PMCER_PMCI 0x001
|
||||
#define PMCER_ALL 0x1FF
|
||||
|
||||
/* deep-sleep only */
|
||||
u32 config1;
|
||||
#define PMCCR1_USE_STATE 0x80000000
|
||||
#define PMCCR1_PME_EN 0x00000080
|
||||
#define PMCCR1_ASSERT_PME 0x00000040
|
||||
#define PMCCR1_POWER_OFF 0x00000020
|
||||
|
||||
/* deep-sleep only */
|
||||
u32 config2;
|
||||
};
|
||||
|
||||
struct mpc83xx_rcw {
|
||||
u32 rcwlr;
|
||||
u32 rcwhr;
|
||||
};
|
||||
|
||||
struct mpc83xx_clock {
|
||||
u32 spmr;
|
||||
u32 occr;
|
||||
u32 sccr;
|
||||
};
|
||||
|
||||
struct mpc83xx_syscr {
|
||||
__be32 sgprl;
|
||||
__be32 sgprh;
|
||||
__be32 spridr;
|
||||
__be32 :32;
|
||||
__be32 spcr;
|
||||
__be32 sicrl;
|
||||
__be32 sicrh;
|
||||
};
|
||||
|
||||
struct mpc83xx_saved {
|
||||
u32 sicrl;
|
||||
u32 sicrh;
|
||||
u32 sccr;
|
||||
};
|
||||
|
||||
struct pmc_type {
|
||||
int has_deep_sleep;
|
||||
};
|
||||
|
||||
static struct platform_device *pmc_dev;
|
||||
static int has_deep_sleep, deep_sleeping;
|
||||
static int pmc_irq;
|
||||
static struct mpc83xx_pmc __iomem *pmc_regs;
|
||||
static struct mpc83xx_clock __iomem *clock_regs;
|
||||
static struct mpc83xx_syscr __iomem *syscr_regs;
|
||||
static struct mpc83xx_saved saved_regs;
|
||||
static int is_pci_agent, wake_from_pci;
|
||||
static phys_addr_t immrbase;
|
||||
static int pci_pm_state;
|
||||
static DECLARE_WAIT_QUEUE_HEAD(agent_wq);
|
||||
|
||||
int fsl_deep_sleep(void)
|
||||
{
|
||||
return deep_sleeping;
|
||||
}
|
||||
EXPORT_SYMBOL(fsl_deep_sleep);
|
||||
|
||||
static int mpc83xx_change_state(void)
|
||||
{
|
||||
u32 curr_state;
|
||||
u32 reg_cfg1 = in_be32(&pmc_regs->config1);
|
||||
|
||||
if (is_pci_agent) {
|
||||
pci_pm_state = (reg_cfg1 & PMCCR1_NEXT_STATE) >>
|
||||
PMCCR1_NEXT_STATE_SHIFT;
|
||||
curr_state = reg_cfg1 & PMCCR1_CURR_STATE;
|
||||
|
||||
if (curr_state != pci_pm_state) {
|
||||
reg_cfg1 &= ~PMCCR1_CURR_STATE;
|
||||
reg_cfg1 |= pci_pm_state;
|
||||
out_be32(&pmc_regs->config1, reg_cfg1);
|
||||
|
||||
wake_up(&agent_wq);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t pmc_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
u32 event = in_be32(&pmc_regs->event);
|
||||
int ret = IRQ_NONE;
|
||||
|
||||
if (mpc83xx_change_state())
|
||||
ret = IRQ_HANDLED;
|
||||
|
||||
if (event) {
|
||||
out_be32(&pmc_regs->event, event);
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mpc83xx_suspend_restore_regs(void)
|
||||
{
|
||||
out_be32(&syscr_regs->sicrl, saved_regs.sicrl);
|
||||
out_be32(&syscr_regs->sicrh, saved_regs.sicrh);
|
||||
out_be32(&clock_regs->sccr, saved_regs.sccr);
|
||||
}
|
||||
|
||||
static void mpc83xx_suspend_save_regs(void)
|
||||
{
|
||||
saved_regs.sicrl = in_be32(&syscr_regs->sicrl);
|
||||
saved_regs.sicrh = in_be32(&syscr_regs->sicrh);
|
||||
saved_regs.sccr = in_be32(&clock_regs->sccr);
|
||||
}
|
||||
|
||||
static int mpc83xx_suspend_enter(suspend_state_t state)
|
||||
{
|
||||
int ret = -EAGAIN;
|
||||
|
||||
/* Don't go to sleep if there's a race where pci_pm_state changes
|
||||
* between the agent thread checking it and the PM code disabling
|
||||
* interrupts.
|
||||
*/
|
||||
if (wake_from_pci) {
|
||||
if (pci_pm_state != (deep_sleeping ? 3 : 2))
|
||||
goto out;
|
||||
|
||||
out_be32(&pmc_regs->config1,
|
||||
in_be32(&pmc_regs->config1) | PMCCR1_PME_EN);
|
||||
}
|
||||
|
||||
/* Put the system into low-power mode and the RAM
|
||||
* into self-refresh mode once the core goes to
|
||||
* sleep.
|
||||
*/
|
||||
|
||||
out_be32(&pmc_regs->config, PMCCR_SLPEN | PMCCR_DLPEN);
|
||||
|
||||
/* If it has deep sleep (i.e. it's an 831x or compatible),
|
||||
* disable power to the core upon entering sleep mode. This will
|
||||
* require going through the boot firmware upon a wakeup event.
|
||||
*/
|
||||
|
||||
if (deep_sleeping) {
|
||||
mpc83xx_suspend_save_regs();
|
||||
|
||||
out_be32(&pmc_regs->mask, PMCER_ALL);
|
||||
|
||||
out_be32(&pmc_regs->config1,
|
||||
in_be32(&pmc_regs->config1) | PMCCR1_POWER_OFF);
|
||||
|
||||
enable_kernel_fp();
|
||||
|
||||
mpc83xx_enter_deep_sleep(immrbase);
|
||||
|
||||
out_be32(&pmc_regs->config1,
|
||||
in_be32(&pmc_regs->config1) & ~PMCCR1_POWER_OFF);
|
||||
|
||||
out_be32(&pmc_regs->mask, PMCER_PMCI);
|
||||
|
||||
mpc83xx_suspend_restore_regs();
|
||||
} else {
|
||||
out_be32(&pmc_regs->mask, PMCER_PMCI);
|
||||
|
||||
mpc6xx_enter_standby();
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
out_be32(&pmc_regs->config1,
|
||||
in_be32(&pmc_regs->config1) & ~PMCCR1_PME_EN);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mpc83xx_suspend_end(void)
|
||||
{
|
||||
deep_sleeping = 0;
|
||||
}
|
||||
|
||||
static int mpc83xx_suspend_valid(suspend_state_t state)
|
||||
{
|
||||
return state == PM_SUSPEND_STANDBY || state == PM_SUSPEND_MEM;
|
||||
}
|
||||
|
||||
static int mpc83xx_suspend_begin(suspend_state_t state)
|
||||
{
|
||||
switch (state) {
|
||||
case PM_SUSPEND_STANDBY:
|
||||
deep_sleeping = 0;
|
||||
return 0;
|
||||
|
||||
case PM_SUSPEND_MEM:
|
||||
if (has_deep_sleep)
|
||||
deep_sleeping = 1;
|
||||
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int agent_thread_fn(void *data)
|
||||
{
|
||||
while (1) {
|
||||
wait_event_interruptible(agent_wq, pci_pm_state >= 2);
|
||||
try_to_freeze();
|
||||
|
||||
if (signal_pending(current) || pci_pm_state < 2)
|
||||
continue;
|
||||
|
||||
/* With a preemptible kernel (or SMP), this could race with
|
||||
* a userspace-driven suspend request. It's probably best
|
||||
* to avoid mixing the two with such a configuration (or
|
||||
* else fix it by adding a mutex to state_store that we can
|
||||
* synchronize with).
|
||||
*/
|
||||
|
||||
wake_from_pci = 1;
|
||||
|
||||
pm_suspend(pci_pm_state == 3 ? PM_SUSPEND_MEM :
|
||||
PM_SUSPEND_STANDBY);
|
||||
|
||||
wake_from_pci = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mpc83xx_set_agent(void)
|
||||
{
|
||||
out_be32(&pmc_regs->config1, PMCCR1_USE_STATE);
|
||||
out_be32(&pmc_regs->mask, PMCER_PMCI);
|
||||
|
||||
kthread_run(agent_thread_fn, NULL, "PCI power mgt");
|
||||
}
|
||||
|
||||
static int mpc83xx_is_pci_agent(void)
|
||||
{
|
||||
struct mpc83xx_rcw __iomem *rcw_regs;
|
||||
int ret;
|
||||
|
||||
rcw_regs = ioremap(get_immrbase() + IMMR_RCW_OFFSET,
|
||||
sizeof(struct mpc83xx_rcw));
|
||||
|
||||
if (!rcw_regs)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = !(in_be32(&rcw_regs->rcwhr) & RCW_PCI_HOST);
|
||||
|
||||
iounmap(rcw_regs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct platform_suspend_ops mpc83xx_suspend_ops = {
|
||||
.valid = mpc83xx_suspend_valid,
|
||||
.begin = mpc83xx_suspend_begin,
|
||||
.enter = mpc83xx_suspend_enter,
|
||||
.end = mpc83xx_suspend_end,
|
||||
};
|
||||
|
||||
static const struct of_device_id pmc_match[];
|
||||
static int pmc_probe(struct platform_device *ofdev)
|
||||
{
|
||||
const struct of_device_id *match;
|
||||
struct device_node *np = ofdev->dev.of_node;
|
||||
struct resource res;
|
||||
const struct pmc_type *type;
|
||||
int ret = 0;
|
||||
|
||||
match = of_match_device(pmc_match, &ofdev->dev);
|
||||
if (!match)
|
||||
return -EINVAL;
|
||||
|
||||
type = match->data;
|
||||
|
||||
if (!of_device_is_available(np))
|
||||
return -ENODEV;
|
||||
|
||||
has_deep_sleep = type->has_deep_sleep;
|
||||
immrbase = get_immrbase();
|
||||
pmc_dev = ofdev;
|
||||
|
||||
is_pci_agent = mpc83xx_is_pci_agent();
|
||||
if (is_pci_agent < 0)
|
||||
return is_pci_agent;
|
||||
|
||||
ret = of_address_to_resource(np, 0, &res);
|
||||
if (ret)
|
||||
return -ENODEV;
|
||||
|
||||
pmc_irq = irq_of_parse_and_map(np, 0);
|
||||
if (pmc_irq != NO_IRQ) {
|
||||
ret = request_irq(pmc_irq, pmc_irq_handler, IRQF_SHARED,
|
||||
"pmc", ofdev);
|
||||
|
||||
if (ret)
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
pmc_regs = ioremap(res.start, sizeof(struct mpc83xx_pmc));
|
||||
|
||||
if (!pmc_regs) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = of_address_to_resource(np, 1, &res);
|
||||
if (ret) {
|
||||
ret = -ENODEV;
|
||||
goto out_pmc;
|
||||
}
|
||||
|
||||
clock_regs = ioremap(res.start, sizeof(struct mpc83xx_pmc));
|
||||
|
||||
if (!clock_regs) {
|
||||
ret = -ENOMEM;
|
||||
goto out_pmc;
|
||||
}
|
||||
|
||||
if (has_deep_sleep) {
|
||||
syscr_regs = ioremap(immrbase + IMMR_SYSCR_OFFSET,
|
||||
sizeof(*syscr_regs));
|
||||
if (!syscr_regs) {
|
||||
ret = -ENOMEM;
|
||||
goto out_syscr;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_pci_agent)
|
||||
mpc83xx_set_agent();
|
||||
|
||||
suspend_set_ops(&mpc83xx_suspend_ops);
|
||||
return 0;
|
||||
|
||||
out_syscr:
|
||||
iounmap(clock_regs);
|
||||
out_pmc:
|
||||
iounmap(pmc_regs);
|
||||
out:
|
||||
if (pmc_irq != NO_IRQ)
|
||||
free_irq(pmc_irq, ofdev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pmc_remove(struct platform_device *ofdev)
|
||||
{
|
||||
return -EPERM;
|
||||
};
|
||||
|
||||
static struct pmc_type pmc_types[] = {
|
||||
{
|
||||
.has_deep_sleep = 1,
|
||||
},
|
||||
{
|
||||
.has_deep_sleep = 0,
|
||||
}
|
||||
};
|
||||
|
||||
static const struct of_device_id pmc_match[] = {
|
||||
{
|
||||
.compatible = "fsl,mpc8313-pmc",
|
||||
.data = &pmc_types[0],
|
||||
},
|
||||
{
|
||||
.compatible = "fsl,mpc8349-pmc",
|
||||
.data = &pmc_types[1],
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver pmc_driver = {
|
||||
.driver = {
|
||||
.name = "mpc83xx-pmc",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = pmc_match,
|
||||
},
|
||||
.probe = pmc_probe,
|
||||
.remove = pmc_remove
|
||||
};
|
||||
|
||||
static int pmc_init(void)
|
||||
{
|
||||
return platform_driver_register(&pmc_driver);
|
||||
}
|
||||
|
||||
module_init(pmc_init);
|
||||
254
arch/powerpc/platforms/83xx/usb.c
Normal file
254
arch/powerpc/platforms/83xx/usb.c
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
/*
|
||||
* Freescale 83xx USB SOC setup code
|
||||
*
|
||||
* Copyright (C) 2007 Freescale Semiconductor, Inc.
|
||||
* Author: Li Yang
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/prom.h>
|
||||
#include <sysdev/fsl_soc.h>
|
||||
|
||||
#include "mpc83xx.h"
|
||||
|
||||
|
||||
#ifdef CONFIG_PPC_MPC834x
|
||||
int mpc834x_usb_cfg(void)
|
||||
{
|
||||
unsigned long sccr, sicrl, sicrh;
|
||||
void __iomem *immap;
|
||||
struct device_node *np = NULL;
|
||||
int port0_is_dr = 0, port1_is_dr = 0;
|
||||
const void *prop, *dr_mode;
|
||||
|
||||
immap = ioremap(get_immrbase(), 0x1000);
|
||||
if (!immap)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Read registers */
|
||||
/* Note: DR and MPH must use the same clock setting in SCCR */
|
||||
sccr = in_be32(immap + MPC83XX_SCCR_OFFS) & ~MPC83XX_SCCR_USB_MASK;
|
||||
sicrl = in_be32(immap + MPC83XX_SICRL_OFFS) & ~MPC834X_SICRL_USB_MASK;
|
||||
sicrh = in_be32(immap + MPC83XX_SICRH_OFFS) & ~MPC834X_SICRH_USB_UTMI;
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "fsl-usb2-dr");
|
||||
if (np) {
|
||||
sccr |= MPC83XX_SCCR_USB_DRCM_11; /* 1:3 */
|
||||
|
||||
prop = of_get_property(np, "phy_type", NULL);
|
||||
port1_is_dr = 1;
|
||||
if (prop && (!strcmp(prop, "utmi") ||
|
||||
!strcmp(prop, "utmi_wide"))) {
|
||||
sicrl |= MPC834X_SICRL_USB0 | MPC834X_SICRL_USB1;
|
||||
sicrh |= MPC834X_SICRH_USB_UTMI;
|
||||
port0_is_dr = 1;
|
||||
} else if (prop && !strcmp(prop, "serial")) {
|
||||
dr_mode = of_get_property(np, "dr_mode", NULL);
|
||||
if (dr_mode && !strcmp(dr_mode, "otg")) {
|
||||
sicrl |= MPC834X_SICRL_USB0 | MPC834X_SICRL_USB1;
|
||||
port0_is_dr = 1;
|
||||
} else {
|
||||
sicrl |= MPC834X_SICRL_USB1;
|
||||
}
|
||||
} else if (prop && !strcmp(prop, "ulpi")) {
|
||||
sicrl |= MPC834X_SICRL_USB1;
|
||||
} else {
|
||||
printk(KERN_WARNING "834x USB PHY type not supported\n");
|
||||
}
|
||||
of_node_put(np);
|
||||
}
|
||||
np = of_find_compatible_node(NULL, NULL, "fsl-usb2-mph");
|
||||
if (np) {
|
||||
sccr |= MPC83XX_SCCR_USB_MPHCM_11; /* 1:3 */
|
||||
|
||||
prop = of_get_property(np, "port0", NULL);
|
||||
if (prop) {
|
||||
if (port0_is_dr)
|
||||
printk(KERN_WARNING
|
||||
"834x USB port0 can't be used by both DR and MPH!\n");
|
||||
sicrl &= ~MPC834X_SICRL_USB0;
|
||||
}
|
||||
prop = of_get_property(np, "port1", NULL);
|
||||
if (prop) {
|
||||
if (port1_is_dr)
|
||||
printk(KERN_WARNING
|
||||
"834x USB port1 can't be used by both DR and MPH!\n");
|
||||
sicrl &= ~MPC834X_SICRL_USB1;
|
||||
}
|
||||
of_node_put(np);
|
||||
}
|
||||
|
||||
/* Write back */
|
||||
out_be32(immap + MPC83XX_SCCR_OFFS, sccr);
|
||||
out_be32(immap + MPC83XX_SICRL_OFFS, sicrl);
|
||||
out_be32(immap + MPC83XX_SICRH_OFFS, sicrh);
|
||||
|
||||
iounmap(immap);
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_PPC_MPC834x */
|
||||
|
||||
#ifdef CONFIG_PPC_MPC831x
|
||||
int mpc831x_usb_cfg(void)
|
||||
{
|
||||
u32 temp;
|
||||
void __iomem *immap, *usb_regs;
|
||||
struct device_node *np = NULL;
|
||||
struct device_node *immr_node = NULL;
|
||||
const void *prop;
|
||||
struct resource res;
|
||||
int ret = 0;
|
||||
#ifdef CONFIG_USB_OTG
|
||||
const void *dr_mode;
|
||||
#endif
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "fsl-usb2-dr");
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
prop = of_get_property(np, "phy_type", NULL);
|
||||
|
||||
/* Map IMMR space for pin and clock settings */
|
||||
immap = ioremap(get_immrbase(), 0x1000);
|
||||
if (!immap) {
|
||||
of_node_put(np);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Configure clock */
|
||||
immr_node = of_get_parent(np);
|
||||
if (immr_node && (of_device_is_compatible(immr_node, "fsl,mpc8315-immr") ||
|
||||
of_device_is_compatible(immr_node, "fsl,mpc8308-immr")))
|
||||
clrsetbits_be32(immap + MPC83XX_SCCR_OFFS,
|
||||
MPC8315_SCCR_USB_MASK,
|
||||
MPC8315_SCCR_USB_DRCM_01);
|
||||
else
|
||||
clrsetbits_be32(immap + MPC83XX_SCCR_OFFS,
|
||||
MPC83XX_SCCR_USB_MASK,
|
||||
MPC83XX_SCCR_USB_DRCM_11);
|
||||
|
||||
/* Configure pin mux for ULPI. There is no pin mux for UTMI */
|
||||
if (prop && !strcmp(prop, "ulpi")) {
|
||||
if (of_device_is_compatible(immr_node, "fsl,mpc8308-immr")) {
|
||||
clrsetbits_be32(immap + MPC83XX_SICRH_OFFS,
|
||||
MPC8308_SICRH_USB_MASK,
|
||||
MPC8308_SICRH_USB_ULPI);
|
||||
} else if (of_device_is_compatible(immr_node, "fsl,mpc8315-immr")) {
|
||||
clrsetbits_be32(immap + MPC83XX_SICRL_OFFS,
|
||||
MPC8315_SICRL_USB_MASK,
|
||||
MPC8315_SICRL_USB_ULPI);
|
||||
clrsetbits_be32(immap + MPC83XX_SICRH_OFFS,
|
||||
MPC8315_SICRH_USB_MASK,
|
||||
MPC8315_SICRH_USB_ULPI);
|
||||
} else {
|
||||
clrsetbits_be32(immap + MPC83XX_SICRL_OFFS,
|
||||
MPC831X_SICRL_USB_MASK,
|
||||
MPC831X_SICRL_USB_ULPI);
|
||||
clrsetbits_be32(immap + MPC83XX_SICRH_OFFS,
|
||||
MPC831X_SICRH_USB_MASK,
|
||||
MPC831X_SICRH_USB_ULPI);
|
||||
}
|
||||
}
|
||||
|
||||
iounmap(immap);
|
||||
|
||||
if (immr_node)
|
||||
of_node_put(immr_node);
|
||||
|
||||
/* Map USB SOC space */
|
||||
ret = of_address_to_resource(np, 0, &res);
|
||||
if (ret) {
|
||||
of_node_put(np);
|
||||
return ret;
|
||||
}
|
||||
usb_regs = ioremap(res.start, resource_size(&res));
|
||||
|
||||
/* Using on-chip PHY */
|
||||
if (prop && (!strcmp(prop, "utmi_wide") ||
|
||||
!strcmp(prop, "utmi"))) {
|
||||
u32 refsel;
|
||||
|
||||
if (of_device_is_compatible(immr_node, "fsl,mpc8308-immr"))
|
||||
goto out;
|
||||
|
||||
if (of_device_is_compatible(immr_node, "fsl,mpc8315-immr"))
|
||||
refsel = CONTROL_REFSEL_24MHZ;
|
||||
else
|
||||
refsel = CONTROL_REFSEL_48MHZ;
|
||||
/* Set UTMI_PHY_EN and REFSEL */
|
||||
out_be32(usb_regs + FSL_USB2_CONTROL_OFFS,
|
||||
CONTROL_UTMI_PHY_EN | refsel);
|
||||
/* Using external UPLI PHY */
|
||||
} else if (prop && !strcmp(prop, "ulpi")) {
|
||||
/* Set PHY_CLK_SEL to ULPI */
|
||||
temp = CONTROL_PHY_CLK_SEL_ULPI;
|
||||
#ifdef CONFIG_USB_OTG
|
||||
/* Set OTG_PORT */
|
||||
if (!of_device_is_compatible(immr_node, "fsl,mpc8308-immr")) {
|
||||
dr_mode = of_get_property(np, "dr_mode", NULL);
|
||||
if (dr_mode && !strcmp(dr_mode, "otg"))
|
||||
temp |= CONTROL_OTG_PORT;
|
||||
}
|
||||
#endif /* CONFIG_USB_OTG */
|
||||
out_be32(usb_regs + FSL_USB2_CONTROL_OFFS, temp);
|
||||
} else {
|
||||
printk(KERN_WARNING "831x USB PHY type not supported\n");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
out:
|
||||
iounmap(usb_regs);
|
||||
of_node_put(np);
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_PPC_MPC831x */
|
||||
|
||||
#ifdef CONFIG_PPC_MPC837x
|
||||
int mpc837x_usb_cfg(void)
|
||||
{
|
||||
void __iomem *immap;
|
||||
struct device_node *np = NULL;
|
||||
const void *prop;
|
||||
int ret = 0;
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "fsl-usb2-dr");
|
||||
if (!np || !of_device_is_available(np))
|
||||
return -ENODEV;
|
||||
prop = of_get_property(np, "phy_type", NULL);
|
||||
|
||||
if (!prop || (strcmp(prop, "ulpi") && strcmp(prop, "serial"))) {
|
||||
printk(KERN_WARNING "837x USB PHY type not supported\n");
|
||||
of_node_put(np);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Map IMMR space for pin and clock settings */
|
||||
immap = ioremap(get_immrbase(), 0x1000);
|
||||
if (!immap) {
|
||||
of_node_put(np);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Configure clock */
|
||||
clrsetbits_be32(immap + MPC83XX_SCCR_OFFS, MPC837X_SCCR_USB_DRCM_11,
|
||||
MPC837X_SCCR_USB_DRCM_11);
|
||||
|
||||
/* Configure pin mux for ULPI/serial */
|
||||
clrsetbits_be32(immap + MPC83XX_SICRL_OFFS, MPC837X_SICRL_USB_MASK,
|
||||
MPC837X_SICRL_USB_ULPI);
|
||||
|
||||
iounmap(immap);
|
||||
of_node_put(np);
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_PPC_MPC837x */
|
||||
Loading…
Add table
Add a link
Reference in a new issue