mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 18:51:56 -04:00
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (158 commits) powerpc: Fix CHRP PCI config access for indirect_pci powerpc/chrp: Fix detection of Python PCI host bridge on IBM CHRPs powerpc: Fix 32-bit SMP boot on CHRP powerpc: Fix link errors on 32-bit machines using legacy DMA powerpc/pci: Improve detection of unassigned bridge resources hvc_console: Fix free_irq in spinlocked section powerpc: Get USE_STRICT_MM_TYPECHECKS working again powerpc: Reflect the used arguments in machine_init() prototype powerpc: Fix DMA offset for non-coherent DMA powerpc: fix fsl_upm nand driver modular build powerpc/83xx: add NAND support for the MPC8360E-RDK boards powerpc: FPGA support for GE Fanuc SBC610 i2c: MPC8349E-mITX Power Management and GPIO expander driver powerpc: reserve two DMA channels for audio in MPC8610 HPCD device tree powerpc: document the "fsl,ssi-dma-channel" compatible property powerpc: disable CHRP and PMAC support in various defconfigs OF: add fsl,mcu-mpc8349emitx to the exception list powerpc/83xx: add DS1374 RTC support for the MPC837xE-MDS boards powerpc: remove support for bootmem-allocated memory for the DIU driver powerpc: remove non-dependent load fsl_booke PTE_64BIT ...
This commit is contained in:
commit
5f2434a66d
325 changed files with 13655 additions and 6682 deletions
|
|
@ -52,7 +52,7 @@ static int __devinit pata_of_platform_probe(struct of_device *ofdev,
|
|||
|
||||
ret = of_irq_to_resource(dn, 0, &irq_res);
|
||||
if (ret == NO_IRQ)
|
||||
irq_res.start = irq_res.end = -1;
|
||||
irq_res.start = irq_res.end = 0;
|
||||
else
|
||||
irq_res.flags = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -4172,7 +4172,7 @@ static int __init floppy_init(void)
|
|||
int i, unit, drive;
|
||||
int err, dr;
|
||||
|
||||
#if defined(CONFIG_PPC_MERGE)
|
||||
#if defined(CONFIG_PPC)
|
||||
if (check_legacy_ioport(FDC1))
|
||||
return -ENODEV;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -249,7 +249,6 @@ static int send_request(struct request *req)
|
|||
struct HvLpEvent *hev;
|
||||
struct scatterlist sg[VIOMAXBLOCKDMA];
|
||||
int sgindex;
|
||||
int statindex;
|
||||
struct viodasd_device *d;
|
||||
unsigned long flags;
|
||||
|
||||
|
|
@ -258,11 +257,9 @@ static int send_request(struct request *req)
|
|||
if (rq_data_dir(req) == READ) {
|
||||
direction = DMA_FROM_DEVICE;
|
||||
viocmd = viomajorsubtype_blockio | vioblockread;
|
||||
statindex = 0;
|
||||
} else {
|
||||
direction = DMA_TO_DEVICE;
|
||||
viocmd = viomajorsubtype_blockio | vioblockwrite;
|
||||
statindex = 1;
|
||||
}
|
||||
|
||||
d = req->rq_disk->private_data;
|
||||
|
|
|
|||
|
|
@ -367,13 +367,13 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
|
|||
spin_lock_irqsave(&hp->lock, flags);
|
||||
|
||||
if (--hp->count == 0) {
|
||||
if (hp->ops->notifier_del)
|
||||
hp->ops->notifier_del(hp, hp->data);
|
||||
|
||||
/* We are done with the tty pointer now. */
|
||||
hp->tty = NULL;
|
||||
spin_unlock_irqrestore(&hp->lock, flags);
|
||||
|
||||
if (hp->ops->notifier_del)
|
||||
hp->ops->notifier_del(hp, hp->data);
|
||||
|
||||
/*
|
||||
* Chain calls chars_in_buffer() and returns immediately if
|
||||
* there is no buffered data otherwise sleeps on a wait queue
|
||||
|
|
@ -416,11 +416,11 @@ static void hvc_hangup(struct tty_struct *tty)
|
|||
hp->n_outbuf = 0;
|
||||
hp->tty = NULL;
|
||||
|
||||
spin_unlock_irqrestore(&hp->lock, flags);
|
||||
|
||||
if (hp->ops->notifier_del)
|
||||
hp->ops->notifier_del(hp, hp->data);
|
||||
|
||||
spin_unlock_irqrestore(&hp->lock, flags);
|
||||
|
||||
while(temp_open_count) {
|
||||
--temp_open_count;
|
||||
kref_put(&hp->kref, destroy_hvc_struct);
|
||||
|
|
|
|||
|
|
@ -2695,7 +2695,7 @@ static __devinit void default_find_bmc(void)
|
|||
for (i = 0; ; i++) {
|
||||
if (!ipmi_defaults[i].port)
|
||||
break;
|
||||
#ifdef CONFIG_PPC_MERGE
|
||||
#ifdef CONFIG_PPC
|
||||
if (check_legacy_ioport(ipmi_defaults[i].port))
|
||||
continue;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#include <linux/mutex.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/types.h>
|
||||
#include <asm/of_device.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
enum ams_irq {
|
||||
AMS_IRQ_FREEFALL = 0x01,
|
||||
|
|
|
|||
|
|
@ -312,7 +312,6 @@ static struct i2c_adapter mpc_ops = {
|
|||
.name = "MPC adapter",
|
||||
.id = I2C_HW_MPC107,
|
||||
.algo = &mpc_algo,
|
||||
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
|
||||
.timeout = 1,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ static int __devinit pca_isa_probe(struct device *dev, unsigned int id)
|
|||
|
||||
dev_info(dev, "i/o base %#08lx. irq %d\n", base, irq);
|
||||
|
||||
#ifdef CONFIG_PPC_MERGE
|
||||
#ifdef CONFIG_PPC
|
||||
if (check_legacy_ioport(base)) {
|
||||
dev_err(dev, "I/O address %#08lx is not available\n", base);
|
||||
goto out;
|
||||
|
|
|
|||
|
|
@ -172,4 +172,15 @@ config MENELAUS
|
|||
and other features that are often used in portable devices like
|
||||
cell phones and PDAs.
|
||||
|
||||
config MCU_MPC8349EMITX
|
||||
tristate "MPC8349E-mITX MCU driver"
|
||||
depends on I2C && PPC_83xx
|
||||
select GENERIC_GPIO
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
help
|
||||
Say Y here to enable soft power-off functionality on the Freescale
|
||||
boards with the MPC8349E-mITX-compatible MCU chips. This driver will
|
||||
also register MCU GPIOs with the generic GPIO API, so you'll able
|
||||
to use MCU pins as GPIOs.
|
||||
|
||||
endmenu
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o
|
|||
obj-$(CONFIG_TPS65010) += tps65010.o
|
||||
obj-$(CONFIG_MENELAUS) += menelaus.o
|
||||
obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o
|
||||
obj-$(CONFIG_MCU_MPC8349EMITX) += mcu_mpc8349emitx.o
|
||||
|
||||
ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
|
||||
EXTRA_CFLAGS += -DDEBUG
|
||||
|
|
|
|||
209
drivers/i2c/chips/mcu_mpc8349emitx.c
Normal file
209
drivers/i2c/chips/mcu_mpc8349emitx.c
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
* 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/init.h>
|
||||
#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 <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_NUM_GPIO 2
|
||||
|
||||
struct mcu {
|
||||
struct mutex lock;
|
||||
struct device_node *np;
|
||||
struct i2c_client *client;
|
||||
struct of_gpio_chip of_gc;
|
||||
u8 reg_ctrl;
|
||||
};
|
||||
|
||||
static struct mcu *glob_mcu;
|
||||
|
||||
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(glob_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 of_gpio_chip *of_gc = to_of_gpio_chip(gc);
|
||||
struct mcu *mcu = container_of(of_gc, struct mcu, of_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 of_gpio_chip *of_gc = &mcu->of_gc;
|
||||
struct gpio_chip *gc = &of_gc->gc;
|
||||
int ret;
|
||||
|
||||
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;
|
||||
of_gc->gpio_cells = 2;
|
||||
of_gc->xlate = of_gpio_simple_xlate;
|
||||
|
||||
np->data = of_gc;
|
||||
mcu->np = np;
|
||||
|
||||
/*
|
||||
* We don't want to lose the node, its ->data and ->full_name...
|
||||
* So, if succeeded, we don't put the node here.
|
||||
*/
|
||||
ret = gpiochip_add(gc);
|
||||
if (ret)
|
||||
of_node_put(np);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mcu_gpiochip_remove(struct mcu *mcu)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = gpiochip_remove(&mcu->of_gc.gc);
|
||||
if (ret)
|
||||
return ret;
|
||||
of_node_put(mcu->np);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit 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");
|
||||
}
|
||||
|
||||
return 0;
|
||||
err:
|
||||
kfree(mcu);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit mcu_remove(struct i2c_client *client)
|
||||
{
|
||||
struct mcu *mcu = i2c_get_clientdata(client);
|
||||
int ret;
|
||||
|
||||
if (glob_mcu == mcu) {
|
||||
ppc_md.power_off = NULL;
|
||||
glob_mcu = NULL;
|
||||
}
|
||||
|
||||
ret = mcu_gpiochip_remove(mcu);
|
||||
if (ret)
|
||||
return ret;
|
||||
i2c_set_clientdata(client, NULL);
|
||||
kfree(mcu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id mcu_ids[] = {
|
||||
{ "mcu-mpc8349emitx", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, mcu_ids);
|
||||
|
||||
static struct i2c_driver mcu_driver = {
|
||||
.driver = {
|
||||
.name = "mcu-mpc8349emitx",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = mcu_probe,
|
||||
.remove = __devexit_p(mcu_remove),
|
||||
.id_table = mcu_ids,
|
||||
};
|
||||
|
||||
static int __init mcu_init(void)
|
||||
{
|
||||
return i2c_add_driver(&mcu_driver);
|
||||
}
|
||||
module_init(mcu_init);
|
||||
|
||||
static void __exit mcu_exit(void)
|
||||
{
|
||||
i2c_del_driver(&mcu_driver);
|
||||
}
|
||||
module_exit(mcu_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Power Management and GPIO expander driver for "
|
||||
"MPC8349E-mITX-compatible MCU");
|
||||
MODULE_AUTHOR("Anton Vorontsov <[email protected]>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -67,7 +67,7 @@ static inline int i8042_platform_init(void)
|
|||
* On some platforms touching the i8042 data register region can do really
|
||||
* bad things. Because of this the region is always reserved on such boxes.
|
||||
*/
|
||||
#if defined(CONFIG_PPC_MERGE)
|
||||
#if defined(CONFIG_PPC)
|
||||
if (check_legacy_ioport(I8042_DATA_REG))
|
||||
return -ENODEV;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -62,3 +62,15 @@ config IBM_NEW_EMAC_TAH
|
|||
config IBM_NEW_EMAC_EMAC4
|
||||
bool
|
||||
default n
|
||||
|
||||
config IBM_NEW_EMAC_NO_FLOW_CTRL
|
||||
bool
|
||||
default n
|
||||
|
||||
config IBM_NEW_EMAC_MAL_CLR_ICINTSTAT
|
||||
bool
|
||||
default n
|
||||
|
||||
config IBM_NEW_EMAC_MAL_COMMON_ERR
|
||||
bool
|
||||
default n
|
||||
|
|
|
|||
|
|
@ -202,13 +202,15 @@ static inline int emac_phy_supports_gige(int phy_mode)
|
|||
{
|
||||
return phy_mode == PHY_MODE_GMII ||
|
||||
phy_mode == PHY_MODE_RGMII ||
|
||||
phy_mode == PHY_MODE_SGMII ||
|
||||
phy_mode == PHY_MODE_TBI ||
|
||||
phy_mode == PHY_MODE_RTBI;
|
||||
}
|
||||
|
||||
static inline int emac_phy_gpcs(int phy_mode)
|
||||
{
|
||||
return phy_mode == PHY_MODE_TBI ||
|
||||
return phy_mode == PHY_MODE_SGMII ||
|
||||
phy_mode == PHY_MODE_TBI ||
|
||||
phy_mode == PHY_MODE_RTBI;
|
||||
}
|
||||
|
||||
|
|
@ -562,8 +564,9 @@ static int emac_configure(struct emac_instance *dev)
|
|||
switch (dev->phy.speed) {
|
||||
case SPEED_1000:
|
||||
if (emac_phy_gpcs(dev->phy.mode)) {
|
||||
mr1 |= EMAC_MR1_MF_1000GPCS |
|
||||
EMAC_MR1_MF_IPPA(dev->phy.address);
|
||||
mr1 |= EMAC_MR1_MF_1000GPCS | EMAC_MR1_MF_IPPA(
|
||||
(dev->phy.gpcs_address != 0xffffffff) ?
|
||||
dev->phy.gpcs_address : dev->phy.address);
|
||||
|
||||
/* Put some arbitrary OUI, Manuf & Rev IDs so we can
|
||||
* identify this GPCS PHY later.
|
||||
|
|
@ -675,8 +678,12 @@ static int emac_configure(struct emac_instance *dev)
|
|||
out_be32(&p->iser, r);
|
||||
|
||||
/* We need to take GPCS PHY out of isolate mode after EMAC reset */
|
||||
if (emac_phy_gpcs(dev->phy.mode))
|
||||
emac_mii_reset_phy(&dev->phy);
|
||||
if (emac_phy_gpcs(dev->phy.mode)) {
|
||||
if (dev->phy.gpcs_address != 0xffffffff)
|
||||
emac_mii_reset_gpcs(&dev->phy);
|
||||
else
|
||||
emac_mii_reset_phy(&dev->phy);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -881,7 +888,9 @@ static int emac_mdio_read(struct net_device *ndev, int id, int reg)
|
|||
struct emac_instance *dev = netdev_priv(ndev);
|
||||
int res;
|
||||
|
||||
res = __emac_mdio_read(dev->mdio_instance ? dev->mdio_instance : dev,
|
||||
res = __emac_mdio_read((dev->mdio_instance &&
|
||||
dev->phy.gpcs_address != id) ?
|
||||
dev->mdio_instance : dev,
|
||||
(u8) id, (u8) reg);
|
||||
return res;
|
||||
}
|
||||
|
|
@ -890,7 +899,9 @@ static void emac_mdio_write(struct net_device *ndev, int id, int reg, int val)
|
|||
{
|
||||
struct emac_instance *dev = netdev_priv(ndev);
|
||||
|
||||
__emac_mdio_write(dev->mdio_instance ? dev->mdio_instance : dev,
|
||||
__emac_mdio_write((dev->mdio_instance &&
|
||||
dev->phy.gpcs_address != id) ?
|
||||
dev->mdio_instance : dev,
|
||||
(u8) id, (u8) reg, (u16) val);
|
||||
}
|
||||
|
||||
|
|
@ -2382,7 +2393,11 @@ static int __devinit emac_init_phy(struct emac_instance *dev)
|
|||
* XXX I probably should move these settings to the dev tree
|
||||
*/
|
||||
dev->phy.address = -1;
|
||||
dev->phy.features = SUPPORTED_100baseT_Full | SUPPORTED_MII;
|
||||
dev->phy.features = SUPPORTED_MII;
|
||||
if (emac_phy_supports_gige(dev->phy_mode))
|
||||
dev->phy.features |= SUPPORTED_1000baseT_Full;
|
||||
else
|
||||
dev->phy.features |= SUPPORTED_100baseT_Full;
|
||||
dev->phy.pause = 1;
|
||||
|
||||
return 0;
|
||||
|
|
@ -2421,7 +2436,9 @@ static int __devinit emac_init_phy(struct emac_instance *dev)
|
|||
* Note that the busy_phy_map is currently global
|
||||
* while it should probably be per-ASIC...
|
||||
*/
|
||||
dev->phy.address = dev->cell_index;
|
||||
dev->phy.gpcs_address = dev->gpcs_address;
|
||||
if (dev->phy.gpcs_address == 0xffffffff)
|
||||
dev->phy.address = dev->cell_index;
|
||||
}
|
||||
|
||||
emac_configure(dev);
|
||||
|
|
@ -2531,6 +2548,8 @@ static int __devinit emac_init_config(struct emac_instance *dev)
|
|||
dev->phy_address = 0xffffffff;
|
||||
if (emac_read_uint_prop(np, "phy-map", &dev->phy_map, 0))
|
||||
dev->phy_map = 0xffffffff;
|
||||
if (emac_read_uint_prop(np, "gpcs-address", &dev->gpcs_address, 0))
|
||||
dev->gpcs_address = 0xffffffff;
|
||||
if (emac_read_uint_prop(np->parent, "clock-frequency", &dev->opb_bus_freq, 1))
|
||||
return -ENXIO;
|
||||
if (emac_read_uint_prop(np, "tah-device", &dev->tah_ph, 0))
|
||||
|
|
@ -2585,6 +2604,8 @@ static int __devinit emac_init_config(struct emac_instance *dev)
|
|||
if (of_device_is_compatible(np, "ibm,emac-440ep") ||
|
||||
of_device_is_compatible(np, "ibm,emac-440gr"))
|
||||
dev->features |= EMAC_FTR_440EP_PHY_CLK_FIX;
|
||||
if (of_device_is_compatible(np, "ibm,emac-405ez"))
|
||||
dev->features |= EMAC_FTR_NO_FLOW_CONTROL_40x;
|
||||
}
|
||||
|
||||
/* Fixup some feature bits based on the device tree */
|
||||
|
|
@ -2842,6 +2863,9 @@ static int __devinit emac_probe(struct of_device *ofdev,
|
|||
ndev->dev_addr[0], ndev->dev_addr[1], ndev->dev_addr[2],
|
||||
ndev->dev_addr[3], ndev->dev_addr[4], ndev->dev_addr[5]);
|
||||
|
||||
if (dev->phy_mode == PHY_MODE_SGMII)
|
||||
printk(KERN_NOTICE "%s: in SGMII mode\n", ndev->name);
|
||||
|
||||
if (dev->phy.address >= 0)
|
||||
printk("%s: found %s PHY (0x%02x)\n", ndev->name,
|
||||
dev->phy.def->name, dev->phy.address);
|
||||
|
|
|
|||
|
|
@ -190,6 +190,9 @@ struct emac_instance {
|
|||
struct delayed_work link_work;
|
||||
int link_polling;
|
||||
|
||||
/* GPCS PHY infos */
|
||||
u32 gpcs_address;
|
||||
|
||||
/* Shared MDIO if any */
|
||||
u32 mdio_ph;
|
||||
struct of_device *mdio_dev;
|
||||
|
|
@ -344,6 +347,9 @@ enum {
|
|||
#endif
|
||||
#ifdef CONFIG_IBM_NEW_EMAC_RGMII
|
||||
EMAC_FTR_HAS_RGMII |
|
||||
#endif
|
||||
#ifdef CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL
|
||||
EMAC_FTR_NO_FLOW_CONTROL_40x |
|
||||
#endif
|
||||
EMAC_FTR_460EX_PHY_CLK_FIX |
|
||||
EMAC_FTR_440EP_PHY_CLK_FIX,
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include <linux/delay.h>
|
||||
|
||||
#include "core.h"
|
||||
#include <asm/dcr-regs.h>
|
||||
|
||||
static int mal_count;
|
||||
|
||||
|
|
@ -279,6 +280,10 @@ static irqreturn_t mal_txeob(int irq, void *dev_instance)
|
|||
mal_schedule_poll(mal);
|
||||
set_mal_dcrn(mal, MAL_TXEOBISR, r);
|
||||
|
||||
if (mal_has_feature(mal, MAL_FTR_CLEAR_ICINTSTAT))
|
||||
mtdcri(SDR0, DCRN_SDR_ICINTSTAT,
|
||||
(mfdcri(SDR0, DCRN_SDR_ICINTSTAT) | ICINTSTAT_ICTX));
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
|
@ -293,6 +298,10 @@ static irqreturn_t mal_rxeob(int irq, void *dev_instance)
|
|||
mal_schedule_poll(mal);
|
||||
set_mal_dcrn(mal, MAL_RXEOBISR, r);
|
||||
|
||||
if (mal_has_feature(mal, MAL_FTR_CLEAR_ICINTSTAT))
|
||||
mtdcri(SDR0, DCRN_SDR_ICINTSTAT,
|
||||
(mfdcri(SDR0, DCRN_SDR_ICINTSTAT) | ICINTSTAT_ICRX));
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
|
@ -336,6 +345,25 @@ static irqreturn_t mal_rxde(int irq, void *dev_instance)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t mal_int(int irq, void *dev_instance)
|
||||
{
|
||||
struct mal_instance *mal = dev_instance;
|
||||
u32 esr = get_mal_dcrn(mal, MAL_ESR);
|
||||
|
||||
if (esr & MAL_ESR_EVB) {
|
||||
/* descriptor error */
|
||||
if (esr & MAL_ESR_DE) {
|
||||
if (esr & MAL_ESR_CIDT)
|
||||
return mal_rxde(irq, dev_instance);
|
||||
else
|
||||
return mal_txde(irq, dev_instance);
|
||||
} else { /* SERR */
|
||||
return mal_serr(irq, dev_instance);
|
||||
}
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
void mal_poll_disable(struct mal_instance *mal, struct mal_commac *commac)
|
||||
{
|
||||
/* Spinlock-type semantics: only one caller disable poll at a time */
|
||||
|
|
@ -493,6 +521,8 @@ static int __devinit mal_probe(struct of_device *ofdev,
|
|||
unsigned int dcr_base;
|
||||
const u32 *prop;
|
||||
u32 cfg;
|
||||
unsigned long irqflags;
|
||||
irq_handler_t hdlr_serr, hdlr_txde, hdlr_rxde;
|
||||
|
||||
mal = kzalloc(sizeof(struct mal_instance), GFP_KERNEL);
|
||||
if (!mal) {
|
||||
|
|
@ -542,11 +572,21 @@ static int __devinit mal_probe(struct of_device *ofdev,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (of_device_is_compatible(ofdev->node, "ibm,mcmal-405ez"))
|
||||
mal->features |= (MAL_FTR_CLEAR_ICINTSTAT |
|
||||
MAL_FTR_COMMON_ERR_INT);
|
||||
|
||||
mal->txeob_irq = irq_of_parse_and_map(ofdev->node, 0);
|
||||
mal->rxeob_irq = irq_of_parse_and_map(ofdev->node, 1);
|
||||
mal->serr_irq = irq_of_parse_and_map(ofdev->node, 2);
|
||||
mal->txde_irq = irq_of_parse_and_map(ofdev->node, 3);
|
||||
mal->rxde_irq = irq_of_parse_and_map(ofdev->node, 4);
|
||||
|
||||
if (mal_has_feature(mal, MAL_FTR_COMMON_ERR_INT)) {
|
||||
mal->txde_irq = mal->rxde_irq = mal->serr_irq;
|
||||
} else {
|
||||
mal->txde_irq = irq_of_parse_and_map(ofdev->node, 3);
|
||||
mal->rxde_irq = irq_of_parse_and_map(ofdev->node, 4);
|
||||
}
|
||||
|
||||
if (mal->txeob_irq == NO_IRQ || mal->rxeob_irq == NO_IRQ ||
|
||||
mal->serr_irq == NO_IRQ || mal->txde_irq == NO_IRQ ||
|
||||
mal->rxde_irq == NO_IRQ) {
|
||||
|
|
@ -608,16 +648,26 @@ static int __devinit mal_probe(struct of_device *ofdev,
|
|||
sizeof(struct mal_descriptor) *
|
||||
mal_rx_bd_offset(mal, i));
|
||||
|
||||
err = request_irq(mal->serr_irq, mal_serr, 0, "MAL SERR", mal);
|
||||
if (mal_has_feature(mal, MAL_FTR_COMMON_ERR_INT)) {
|
||||
irqflags = IRQF_SHARED;
|
||||
hdlr_serr = hdlr_txde = hdlr_rxde = mal_int;
|
||||
} else {
|
||||
irqflags = 0;
|
||||
hdlr_serr = mal_serr;
|
||||
hdlr_txde = mal_txde;
|
||||
hdlr_rxde = mal_rxde;
|
||||
}
|
||||
|
||||
err = request_irq(mal->serr_irq, hdlr_serr, irqflags, "MAL SERR", mal);
|
||||
if (err)
|
||||
goto fail2;
|
||||
err = request_irq(mal->txde_irq, mal_txde, 0, "MAL TX DE", mal);
|
||||
err = request_irq(mal->txde_irq, hdlr_txde, irqflags, "MAL TX DE", mal);
|
||||
if (err)
|
||||
goto fail3;
|
||||
err = request_irq(mal->txeob_irq, mal_txeob, 0, "MAL TX EOB", mal);
|
||||
if (err)
|
||||
goto fail4;
|
||||
err = request_irq(mal->rxde_irq, mal_rxde, 0, "MAL RX DE", mal);
|
||||
err = request_irq(mal->rxde_irq, hdlr_rxde, irqflags, "MAL RX DE", mal);
|
||||
if (err)
|
||||
goto fail5;
|
||||
err = request_irq(mal->rxeob_irq, mal_rxeob, 0, "MAL RX EOB", mal);
|
||||
|
|
|
|||
|
|
@ -213,6 +213,8 @@ struct mal_instance {
|
|||
struct of_device *ofdev;
|
||||
int index;
|
||||
spinlock_t lock;
|
||||
|
||||
unsigned int features;
|
||||
};
|
||||
|
||||
static inline u32 get_mal_dcrn(struct mal_instance *mal, int reg)
|
||||
|
|
@ -225,6 +227,38 @@ static inline void set_mal_dcrn(struct mal_instance *mal, int reg, u32 val)
|
|||
dcr_write(mal->dcr_host, reg, val);
|
||||
}
|
||||
|
||||
/* Features of various MAL implementations */
|
||||
|
||||
/* Set if you have interrupt coalescing and you have to clear the SDR
|
||||
* register for TXEOB and RXEOB interrupts to work
|
||||
*/
|
||||
#define MAL_FTR_CLEAR_ICINTSTAT 0x00000001
|
||||
|
||||
/* Set if your MAL has SERR, TXDE, and RXDE OR'd into a single UIC
|
||||
* interrupt
|
||||
*/
|
||||
#define MAL_FTR_COMMON_ERR_INT 0x00000002
|
||||
|
||||
enum {
|
||||
MAL_FTRS_ALWAYS = 0,
|
||||
|
||||
MAL_FTRS_POSSIBLE =
|
||||
#ifdef CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT
|
||||
MAL_FTR_CLEAR_ICINTSTAT |
|
||||
#endif
|
||||
#ifdef CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR
|
||||
MAL_FTR_COMMON_ERR_INT |
|
||||
#endif
|
||||
0,
|
||||
};
|
||||
|
||||
static inline int mal_has_feature(struct mal_instance *dev,
|
||||
unsigned long feature)
|
||||
{
|
||||
return (MAL_FTRS_ALWAYS & feature) ||
|
||||
(MAL_FTRS_POSSIBLE & dev->features & feature);
|
||||
}
|
||||
|
||||
/* Register MAL devices */
|
||||
int mal_init(void);
|
||||
void mal_exit(void);
|
||||
|
|
|
|||
|
|
@ -38,6 +38,16 @@ static inline void phy_write(struct mii_phy *phy, int reg, int val)
|
|||
phy->mdio_write(phy->dev, phy->address, reg, val);
|
||||
}
|
||||
|
||||
static inline int gpcs_phy_read(struct mii_phy *phy, int reg)
|
||||
{
|
||||
return phy->mdio_read(phy->dev, phy->gpcs_address, reg);
|
||||
}
|
||||
|
||||
static inline void gpcs_phy_write(struct mii_phy *phy, int reg, int val)
|
||||
{
|
||||
phy->mdio_write(phy->dev, phy->gpcs_address, reg, val);
|
||||
}
|
||||
|
||||
int emac_mii_reset_phy(struct mii_phy *phy)
|
||||
{
|
||||
int val;
|
||||
|
|
@ -62,6 +72,37 @@ int emac_mii_reset_phy(struct mii_phy *phy)
|
|||
return limit <= 0;
|
||||
}
|
||||
|
||||
int emac_mii_reset_gpcs(struct mii_phy *phy)
|
||||
{
|
||||
int val;
|
||||
int limit = 10000;
|
||||
|
||||
val = gpcs_phy_read(phy, MII_BMCR);
|
||||
val &= ~(BMCR_ISOLATE | BMCR_ANENABLE);
|
||||
val |= BMCR_RESET;
|
||||
gpcs_phy_write(phy, MII_BMCR, val);
|
||||
|
||||
udelay(300);
|
||||
|
||||
while (limit--) {
|
||||
val = gpcs_phy_read(phy, MII_BMCR);
|
||||
if (val >= 0 && (val & BMCR_RESET) == 0)
|
||||
break;
|
||||
udelay(10);
|
||||
}
|
||||
if ((val & BMCR_ISOLATE) && limit > 0)
|
||||
gpcs_phy_write(phy, MII_BMCR, val & ~BMCR_ISOLATE);
|
||||
|
||||
if (limit > 0 && phy->mode == PHY_MODE_SGMII) {
|
||||
/* Configure GPCS interface to recommended setting for SGMII */
|
||||
gpcs_phy_write(phy, 0x04, 0x8120); /* AsymPause, FDX */
|
||||
gpcs_phy_write(phy, 0x07, 0x2801); /* msg_pg, toggle */
|
||||
gpcs_phy_write(phy, 0x00, 0x0140); /* 1Gbps, FDX */
|
||||
}
|
||||
|
||||
return limit <= 0;
|
||||
}
|
||||
|
||||
static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
|
||||
{
|
||||
int ctl, adv;
|
||||
|
|
@ -332,6 +373,33 @@ static int m88e1111_init(struct mii_phy *phy)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int m88e1112_init(struct mii_phy *phy)
|
||||
{
|
||||
/*
|
||||
* Marvell 88E1112 PHY needs to have the SGMII MAC
|
||||
* interace (page 2) properly configured to
|
||||
* communicate with the 460EX/GT GPCS interface.
|
||||
*/
|
||||
|
||||
u16 reg_short;
|
||||
|
||||
pr_debug("%s: Marvell 88E1112 Ethernet\n", __func__);
|
||||
|
||||
/* Set access to Page 2 */
|
||||
phy_write(phy, 0x16, 0x0002);
|
||||
|
||||
phy_write(phy, 0x00, 0x0040); /* 1Gbps */
|
||||
reg_short = (u16)(phy_read(phy, 0x1a));
|
||||
reg_short |= 0x8000; /* bypass Auto-Negotiation */
|
||||
phy_write(phy, 0x1a, reg_short);
|
||||
emac_mii_reset_phy(phy); /* reset MAC interface */
|
||||
|
||||
/* Reset access to Page 0 */
|
||||
phy_write(phy, 0x16, 0x0000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int et1011c_init(struct mii_phy *phy)
|
||||
{
|
||||
u16 reg_short;
|
||||
|
|
@ -384,11 +452,27 @@ static struct mii_phy_def m88e1111_phy_def = {
|
|||
.ops = &m88e1111_phy_ops,
|
||||
};
|
||||
|
||||
static struct mii_phy_ops m88e1112_phy_ops = {
|
||||
.init = m88e1112_init,
|
||||
.setup_aneg = genmii_setup_aneg,
|
||||
.setup_forced = genmii_setup_forced,
|
||||
.poll_link = genmii_poll_link,
|
||||
.read_link = genmii_read_link
|
||||
};
|
||||
|
||||
static struct mii_phy_def m88e1112_phy_def = {
|
||||
.phy_id = 0x01410C90,
|
||||
.phy_id_mask = 0x0ffffff0,
|
||||
.name = "Marvell 88E1112 Ethernet",
|
||||
.ops = &m88e1112_phy_ops,
|
||||
};
|
||||
|
||||
static struct mii_phy_def *mii_phy_table[] = {
|
||||
&et1011c_phy_def,
|
||||
&cis8201_phy_def,
|
||||
&bcm5248_phy_def,
|
||||
&m88e1111_phy_def,
|
||||
&m88e1112_phy_def,
|
||||
&genmii_phy_def,
|
||||
NULL
|
||||
};
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ struct mii_phy {
|
|||
or determined automaticaly */
|
||||
int address; /* PHY address */
|
||||
int mode; /* PHY mode */
|
||||
int gpcs_address; /* GPCS PHY address */
|
||||
|
||||
/* 1: autoneg enabled, 0: disabled */
|
||||
int autoneg;
|
||||
|
|
@ -81,5 +82,6 @@ struct mii_phy {
|
|||
*/
|
||||
int emac_mii_phy_probe(struct mii_phy *phy, int address);
|
||||
int emac_mii_reset_phy(struct mii_phy *phy);
|
||||
int emac_mii_reset_gpcs(struct mii_phy *phy);
|
||||
|
||||
#endif /* __IBM_NEWEMAC_PHY_H */
|
||||
|
|
|
|||
|
|
@ -410,7 +410,7 @@ struct of_modalias_table {
|
|||
char *modalias;
|
||||
};
|
||||
static struct of_modalias_table of_modalias_table[] = {
|
||||
/* Empty for now; add entries as needed */
|
||||
{ "fsl,mcu-mpc8349emitx", "mcu-mpc8349emitx" },
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -420,13 +420,12 @@ static struct of_modalias_table of_modalias_table[] = {
|
|||
* @len: Length of modalias value
|
||||
*
|
||||
* Based on the value of the compatible property, this routine will determine
|
||||
* an appropriate modalias value for a particular device tree node. Three
|
||||
* separate methods are used to derive a modalias value.
|
||||
* an appropriate modalias value for a particular device tree node. Two
|
||||
* separate methods are attempted to derive a modalias value.
|
||||
*
|
||||
* First method is to lookup the compatible value in of_modalias_table.
|
||||
* Second is to look for a "linux,<modalias>" entry in the compatible list
|
||||
* and used that for modalias. Third is to strip off the manufacturer
|
||||
* prefix from the first compatible entry and use the remainder as modalias
|
||||
* Second is to strip off the manufacturer prefix from the first
|
||||
* compatible entry and use the remainder as modalias
|
||||
*
|
||||
* This routine returns 0 on success
|
||||
*/
|
||||
|
|
@ -449,21 +448,7 @@ int of_modalias_node(struct device_node *node, char *modalias, int len)
|
|||
if (!compatible)
|
||||
return -ENODEV;
|
||||
|
||||
/* 2. search for linux,<modalias> entry */
|
||||
p = compatible;
|
||||
while (cplen > 0) {
|
||||
if (!strncmp(p, "linux,", 6)) {
|
||||
p += 6;
|
||||
strlcpy(modalias, p, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
i = strlen(p) + 1;
|
||||
p += i;
|
||||
cplen -= i;
|
||||
}
|
||||
|
||||
/* 3. take first compatible entry and strip manufacturer */
|
||||
/* 2. take first compatible entry and strip manufacturer */
|
||||
p = strchr(compatible, ',');
|
||||
if (!p)
|
||||
return -ENODEV;
|
||||
|
|
@ -473,3 +458,112 @@ int of_modalias_node(struct device_node *node, char *modalias, int len)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(of_modalias_node);
|
||||
|
||||
/**
|
||||
* of_parse_phandles_with_args - Find a node pointed by phandle in a list
|
||||
* @np: pointer to a device tree node containing a list
|
||||
* @list_name: property name that contains a list
|
||||
* @cells_name: property name that specifies phandles' arguments count
|
||||
* @index: index of a phandle to parse out
|
||||
* @out_node: pointer to device_node struct pointer (will be filled)
|
||||
* @out_args: pointer to arguments pointer (will be filled)
|
||||
*
|
||||
* This function is useful to parse lists of phandles and their arguments.
|
||||
* Returns 0 on success and fills out_node and out_args, on error returns
|
||||
* appropriate errno value.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* phandle1: node1 {
|
||||
* #list-cells = <2>;
|
||||
* }
|
||||
*
|
||||
* phandle2: node2 {
|
||||
* #list-cells = <1>;
|
||||
* }
|
||||
*
|
||||
* node3 {
|
||||
* list = <&phandle1 1 2 &phandle2 3>;
|
||||
* }
|
||||
*
|
||||
* To get a device_node of the `node2' node you may call this:
|
||||
* of_parse_phandles_with_args(node3, "list", "#list-cells", 2, &node2, &args);
|
||||
*/
|
||||
int of_parse_phandles_with_args(struct device_node *np, const char *list_name,
|
||||
const char *cells_name, int index,
|
||||
struct device_node **out_node,
|
||||
const void **out_args)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
const u32 *list;
|
||||
const u32 *list_end;
|
||||
int size;
|
||||
int cur_index = 0;
|
||||
struct device_node *node = NULL;
|
||||
const void *args;
|
||||
|
||||
list = of_get_property(np, list_name, &size);
|
||||
if (!list) {
|
||||
ret = -ENOENT;
|
||||
goto err0;
|
||||
}
|
||||
list_end = list + size / sizeof(*list);
|
||||
|
||||
while (list < list_end) {
|
||||
const u32 *cells;
|
||||
const phandle *phandle;
|
||||
|
||||
phandle = list;
|
||||
args = list + 1;
|
||||
|
||||
/* one cell hole in the list = <>; */
|
||||
if (!*phandle) {
|
||||
list++;
|
||||
goto next;
|
||||
}
|
||||
|
||||
node = of_find_node_by_phandle(*phandle);
|
||||
if (!node) {
|
||||
pr_debug("%s: could not find phandle\n",
|
||||
np->full_name);
|
||||
goto err0;
|
||||
}
|
||||
|
||||
cells = of_get_property(node, cells_name, &size);
|
||||
if (!cells || size != sizeof(*cells)) {
|
||||
pr_debug("%s: could not get %s for %s\n",
|
||||
np->full_name, cells_name, node->full_name);
|
||||
goto err1;
|
||||
}
|
||||
|
||||
/* Next phandle is at offset of one phandle cell + #cells */
|
||||
list += 1 + *cells;
|
||||
if (list > list_end) {
|
||||
pr_debug("%s: insufficient arguments length\n",
|
||||
np->full_name);
|
||||
goto err1;
|
||||
}
|
||||
next:
|
||||
if (cur_index == index)
|
||||
break;
|
||||
|
||||
of_node_put(node);
|
||||
node = NULL;
|
||||
cur_index++;
|
||||
}
|
||||
|
||||
if (!node) {
|
||||
ret = -ENOENT;
|
||||
goto err0;
|
||||
}
|
||||
|
||||
*out_node = node;
|
||||
*out_args = args;
|
||||
|
||||
return 0;
|
||||
err1:
|
||||
of_node_put(node);
|
||||
err0:
|
||||
pr_debug("%s failed with status %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(of_parse_phandles_with_args);
|
||||
|
|
|
|||
|
|
@ -28,78 +28,35 @@
|
|||
*/
|
||||
int of_get_gpio(struct device_node *np, int index)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
int ret;
|
||||
struct device_node *gc;
|
||||
struct of_gpio_chip *of_gc = NULL;
|
||||
int size;
|
||||
const u32 *gpios;
|
||||
u32 nr_cells;
|
||||
int i;
|
||||
const void *gpio_spec;
|
||||
const u32 *gpio_cells;
|
||||
int gpio_index = 0;
|
||||
|
||||
gpios = of_get_property(np, "gpios", &size);
|
||||
if (!gpios) {
|
||||
ret = -ENOENT;
|
||||
ret = of_parse_phandles_with_args(np, "gpios", "#gpio-cells", index,
|
||||
&gc, &gpio_spec);
|
||||
if (ret) {
|
||||
pr_debug("%s: can't parse gpios property\n", __func__);
|
||||
goto err0;
|
||||
}
|
||||
nr_cells = size / sizeof(u32);
|
||||
|
||||
for (i = 0; i < nr_cells; gpio_index++) {
|
||||
const phandle *gpio_phandle;
|
||||
|
||||
gpio_phandle = gpios + i;
|
||||
gpio_spec = gpio_phandle + 1;
|
||||
|
||||
/* one cell hole in the gpios = <>; */
|
||||
if (!*gpio_phandle) {
|
||||
if (gpio_index == index)
|
||||
return -ENOENT;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
gc = of_find_node_by_phandle(*gpio_phandle);
|
||||
if (!gc) {
|
||||
pr_debug("%s: could not find phandle for gpios\n",
|
||||
np->full_name);
|
||||
goto err0;
|
||||
}
|
||||
|
||||
of_gc = gc->data;
|
||||
if (!of_gc) {
|
||||
pr_debug("%s: gpio controller %s isn't registered\n",
|
||||
np->full_name, gc->full_name);
|
||||
goto err1;
|
||||
}
|
||||
|
||||
gpio_cells = of_get_property(gc, "#gpio-cells", &size);
|
||||
if (!gpio_cells || size != sizeof(*gpio_cells) ||
|
||||
*gpio_cells != of_gc->gpio_cells) {
|
||||
pr_debug("%s: wrong #gpio-cells for %s\n",
|
||||
np->full_name, gc->full_name);
|
||||
goto err1;
|
||||
}
|
||||
|
||||
/* Next phandle is at phandle cells + #gpio-cells */
|
||||
i += sizeof(*gpio_phandle) / sizeof(u32) + *gpio_cells;
|
||||
if (i >= nr_cells + 1) {
|
||||
pr_debug("%s: insufficient gpio-spec length\n",
|
||||
np->full_name);
|
||||
goto err1;
|
||||
}
|
||||
|
||||
if (gpio_index == index)
|
||||
break;
|
||||
|
||||
of_gc = NULL;
|
||||
of_node_put(gc);
|
||||
}
|
||||
|
||||
of_gc = gc->data;
|
||||
if (!of_gc) {
|
||||
ret = -ENOENT;
|
||||
goto err0;
|
||||
pr_debug("%s: gpio controller %s isn't registered\n",
|
||||
np->full_name, gc->full_name);
|
||||
ret = -ENODEV;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
gpio_cells = of_get_property(gc, "#gpio-cells", &size);
|
||||
if (!gpio_cells || size != sizeof(*gpio_cells) ||
|
||||
*gpio_cells != of_gc->gpio_cells) {
|
||||
pr_debug("%s: wrong #gpio-cells for %s\n",
|
||||
np->full_name, gc->full_name);
|
||||
ret = -EINVAL;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
ret = of_gc->xlate(of_gc, np, gpio_spec);
|
||||
|
|
|
|||
|
|
@ -147,9 +147,5 @@ int rpaphp_register_slot(struct slot *slot)
|
|||
list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head);
|
||||
info("Slot [%s] registered\n", slot->name);
|
||||
return 0;
|
||||
|
||||
sysfs_fail:
|
||||
pci_hp_deregister(php_slot);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1012,7 +1012,7 @@ static int __init isapnp_init(void)
|
|||
printk(KERN_INFO "isapnp: ISA Plug & Play support disabled\n");
|
||||
return 0;
|
||||
}
|
||||
#ifdef CONFIG_PPC_MERGE
|
||||
#ifdef CONFIG_PPC
|
||||
if (check_legacy_ioport(_PIDXR) || check_legacy_ioport(_PNPWRP))
|
||||
return -EINVAL;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -519,7 +519,7 @@ static int __init pnpbios_init(void)
|
|||
{
|
||||
int ret;
|
||||
|
||||
#if defined(CONFIG_PPC_MERGE)
|
||||
#if defined(CONFIG_PPC)
|
||||
if (check_legacy_ioport(PNPBIOS_BASE))
|
||||
return -ENODEV;
|
||||
#endif
|
||||
|
|
@ -577,7 +577,7 @@ static int __init pnpbios_thread_init(void)
|
|||
{
|
||||
struct task_struct *task;
|
||||
|
||||
#if defined(CONFIG_PPC_MERGE)
|
||||
#if defined(CONFIG_PPC)
|
||||
if (check_legacy_ioport(PNPBIOS_BASE))
|
||||
return 0;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1123,42 +1123,6 @@ config SERIAL_CPM_CONSOLE
|
|||
your boot loader (lilo or loadlin) about how to pass options to the
|
||||
kernel at boot time.)
|
||||
|
||||
config SERIAL_CPM_SCC1
|
||||
bool "Support for SCC1 serial port"
|
||||
depends on SERIAL_CPM=y
|
||||
help
|
||||
Select this option to use SCC1 as a serial port
|
||||
|
||||
config SERIAL_CPM_SCC2
|
||||
bool "Support for SCC2 serial port"
|
||||
depends on SERIAL_CPM=y
|
||||
help
|
||||
Select this option to use SCC2 as a serial port
|
||||
|
||||
config SERIAL_CPM_SCC3
|
||||
bool "Support for SCC3 serial port"
|
||||
depends on SERIAL_CPM=y
|
||||
help
|
||||
Select this option to use SCC3 as a serial port
|
||||
|
||||
config SERIAL_CPM_SCC4
|
||||
bool "Support for SCC4 serial port"
|
||||
depends on SERIAL_CPM=y
|
||||
help
|
||||
Select this option to use SCC4 as a serial port
|
||||
|
||||
config SERIAL_CPM_SMC1
|
||||
bool "Support for SMC1 serial port"
|
||||
depends on SERIAL_CPM=y
|
||||
help
|
||||
Select this option to use SMC1 as a serial port
|
||||
|
||||
config SERIAL_CPM_SMC2
|
||||
bool "Support for SMC2 serial port"
|
||||
depends on SERIAL_CPM=y
|
||||
help
|
||||
Select this option to use SMC2 as a serial port
|
||||
|
||||
config SERIAL_SGI_L1_CONSOLE
|
||||
bool "SGI Altix L1 serial console support"
|
||||
depends on IA64_GENERIC || IA64_SGI_SN2
|
||||
|
|
|
|||
|
|
@ -1333,6 +1333,9 @@ static int __devinit cpm_uart_probe(struct of_device *ofdev,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* initialize the device pointer for the port */
|
||||
pinfo->port.dev = &ofdev->dev;
|
||||
|
||||
return uart_add_one_port(&cpm_reg, &pinfo->port);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
|
|||
mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8));
|
||||
dma_addr = (u32)cpm_dpram_phys(mem_addr);
|
||||
} else
|
||||
mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr,
|
||||
mem_addr = dma_alloc_coherent(pinfo->port.dev, memsz, &dma_addr,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (mem_addr == NULL) {
|
||||
|
|
@ -127,8 +127,8 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
|
|||
|
||||
void cpm_uart_freebuf(struct uart_cpm_port *pinfo)
|
||||
{
|
||||
dma_free_coherent(NULL, L1_CACHE_ALIGN(pinfo->rx_nrfifos *
|
||||
pinfo->rx_fifosize) +
|
||||
dma_free_coherent(pinfo->port.dev, L1_CACHE_ALIGN(pinfo->rx_nrfifos *
|
||||
pinfo->rx_fifosize) +
|
||||
L1_CACHE_ALIGN(pinfo->tx_nrfifos *
|
||||
pinfo->tx_fifosize), pinfo->mem_addr,
|
||||
pinfo->dma_addr);
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
|
|||
dma_addr = virt_to_bus(mem_addr);
|
||||
}
|
||||
else
|
||||
mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr,
|
||||
mem_addr = dma_alloc_coherent(pinfo->port.dev, memsz, &dma_addr,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (mem_addr == NULL) {
|
||||
|
|
@ -163,8 +163,8 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
|
|||
|
||||
void cpm_uart_freebuf(struct uart_cpm_port *pinfo)
|
||||
{
|
||||
dma_free_coherent(NULL, L1_CACHE_ALIGN(pinfo->rx_nrfifos *
|
||||
pinfo->rx_fifosize) +
|
||||
dma_free_coherent(pinfo->port.dev, L1_CACHE_ALIGN(pinfo->rx_nrfifos *
|
||||
pinfo->rx_fifosize) +
|
||||
L1_CACHE_ALIGN(pinfo->tx_nrfifos *
|
||||
pinfo->tx_fifosize), (void __force *)pinfo->mem_addr,
|
||||
pinfo->dma_addr);
|
||||
|
|
|
|||
|
|
@ -72,13 +72,8 @@
|
|||
#include <linux/console.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#if defined(CONFIG_PPC_MERGE)
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#else
|
||||
#include <linux/platform_device.h>
|
||||
#endif
|
||||
|
||||
#include <asm/mpc52xx.h>
|
||||
#include <asm/mpc512x.h>
|
||||
|
|
@ -107,12 +102,11 @@ static struct uart_port mpc52xx_uart_ports[MPC52xx_PSC_MAXNUM];
|
|||
* it's cleared, then a memset(...,0,...) should be added to
|
||||
* the console_init
|
||||
*/
|
||||
#if defined(CONFIG_PPC_MERGE)
|
||||
|
||||
/* lookup table for matching device nodes to index numbers */
|
||||
static struct device_node *mpc52xx_uart_nodes[MPC52xx_PSC_MAXNUM];
|
||||
|
||||
static void mpc52xx_uart_of_enumerate(void);
|
||||
#endif
|
||||
|
||||
|
||||
#define PSC(port) ((struct mpc52xx_psc __iomem *)((port)->membase))
|
||||
|
|
@ -255,17 +249,12 @@ static void mpc52xx_psc_cw_restore_ints(struct uart_port *port)
|
|||
/* Search for bus-frequency property in this node or a parent */
|
||||
static unsigned long mpc52xx_getuartclk(void *p)
|
||||
{
|
||||
#if defined(CONFIG_PPC_MERGE)
|
||||
/*
|
||||
* 5200 UARTs have a / 32 prescaler
|
||||
* but the generic serial code assumes 16
|
||||
* so return ipb freq / 2
|
||||
*/
|
||||
return mpc52xx_find_ipb_freq(p) / 2;
|
||||
#else
|
||||
pr_debug("unexpected call to mpc52xx_getuartclk with arch/ppc\n");
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct psc_ops mpc52xx_psc_ops = {
|
||||
|
|
@ -886,10 +875,6 @@ mpc52xx_console_get_options(struct uart_port *port,
|
|||
|
||||
/* CT{U,L}R are write-only ! */
|
||||
*baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD;
|
||||
#if !defined(CONFIG_PPC_MERGE)
|
||||
if (__res.bi_baudrate)
|
||||
*baud = __res.bi_baudrate;
|
||||
#endif
|
||||
|
||||
/* Parse them */
|
||||
switch (mr1 & MPC52xx_PSC_MODE_BITS_MASK) {
|
||||
|
|
@ -946,42 +931,6 @@ mpc52xx_console_write(struct console *co, const char *s, unsigned int count)
|
|||
psc_ops->cw_restore_ints(port);
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_PPC_MERGE)
|
||||
static int __init
|
||||
mpc52xx_console_setup(struct console *co, char *options)
|
||||
{
|
||||
struct uart_port *port = &mpc52xx_uart_ports[co->index];
|
||||
|
||||
int baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD;
|
||||
int bits = 8;
|
||||
int parity = 'n';
|
||||
int flow = 'n';
|
||||
|
||||
if (co->index < 0 || co->index >= MPC52xx_PSC_MAXNUM)
|
||||
return -EINVAL;
|
||||
|
||||
/* Basic port init. Needed since we use some uart_??? func before
|
||||
* real init for early access */
|
||||
spin_lock_init(&port->lock);
|
||||
port->uartclk = __res.bi_ipbfreq / 2; /* Look at CTLR doc */
|
||||
port->ops = &mpc52xx_uart_ops;
|
||||
port->mapbase = MPC52xx_PA(MPC52xx_PSCx_OFFSET(co->index+1));
|
||||
|
||||
/* We ioremap ourself */
|
||||
port->membase = ioremap(port->mapbase, MPC52xx_PSC_SIZE);
|
||||
if (port->membase == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
/* Setup the port parameters accoding to options */
|
||||
if (options)
|
||||
uart_parse_options(options, &baud, &parity, &bits, &flow);
|
||||
else
|
||||
mpc52xx_console_get_options(port, &baud, &parity, &bits, &flow);
|
||||
|
||||
return uart_set_options(port, co, baud, parity, bits, flow);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int __init
|
||||
mpc52xx_console_setup(struct console *co, char *options)
|
||||
|
|
@ -1053,7 +1002,6 @@ mpc52xx_console_setup(struct console *co, char *options)
|
|||
|
||||
return uart_set_options(port, co, baud, parity, bits, flow);
|
||||
}
|
||||
#endif /* defined(CONFIG_PPC_MERGE) */
|
||||
|
||||
|
||||
static struct uart_driver mpc52xx_uart_driver;
|
||||
|
|
@ -1072,9 +1020,7 @@ static struct console mpc52xx_console = {
|
|||
static int __init
|
||||
mpc52xx_console_init(void)
|
||||
{
|
||||
#if defined(CONFIG_PPC_MERGE)
|
||||
mpc52xx_uart_of_enumerate();
|
||||
#endif
|
||||
register_console(&mpc52xx_console);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1100,115 +1046,6 @@ static struct uart_driver mpc52xx_uart_driver = {
|
|||
.cons = MPC52xx_PSC_CONSOLE,
|
||||
};
|
||||
|
||||
|
||||
#if !defined(CONFIG_PPC_MERGE)
|
||||
/* ======================================================================== */
|
||||
/* Platform Driver */
|
||||
/* ======================================================================== */
|
||||
|
||||
static int __devinit
|
||||
mpc52xx_uart_probe(struct platform_device *dev)
|
||||
{
|
||||
struct resource *res = dev->resource;
|
||||
|
||||
struct uart_port *port = NULL;
|
||||
int i, idx, ret;
|
||||
|
||||
/* Check validity & presence */
|
||||
idx = dev->id;
|
||||
if (idx < 0 || idx >= MPC52xx_PSC_MAXNUM)
|
||||
return -EINVAL;
|
||||
|
||||
if (!mpc52xx_match_psc_function(idx, "uart"))
|
||||
return -ENODEV;
|
||||
|
||||
/* Init the port structure */
|
||||
port = &mpc52xx_uart_ports[idx];
|
||||
|
||||
spin_lock_init(&port->lock);
|
||||
port->uartclk = __res.bi_ipbfreq / 2; /* Look at CTLR doc */
|
||||
port->fifosize = 512;
|
||||
port->iotype = UPIO_MEM;
|
||||
port->flags = UPF_BOOT_AUTOCONF |
|
||||
(uart_console(port) ? 0 : UPF_IOREMAP);
|
||||
port->line = idx;
|
||||
port->ops = &mpc52xx_uart_ops;
|
||||
port->dev = &dev->dev;
|
||||
|
||||
/* Search for IRQ and mapbase */
|
||||
for (i = 0 ; i < dev->num_resources ; i++, res++) {
|
||||
if (res->flags & IORESOURCE_MEM)
|
||||
port->mapbase = res->start;
|
||||
else if (res->flags & IORESOURCE_IRQ)
|
||||
port->irq = res->start;
|
||||
}
|
||||
if (!port->irq || !port->mapbase)
|
||||
return -EINVAL;
|
||||
|
||||
/* Add the port to the uart sub-system */
|
||||
ret = uart_add_one_port(&mpc52xx_uart_driver, port);
|
||||
if (!ret)
|
||||
platform_set_drvdata(dev, (void *)port);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
mpc52xx_uart_remove(struct platform_device *dev)
|
||||
{
|
||||
struct uart_port *port = (struct uart_port *) platform_get_drvdata(dev);
|
||||
|
||||
platform_set_drvdata(dev, NULL);
|
||||
|
||||
if (port)
|
||||
uart_remove_one_port(&mpc52xx_uart_driver, port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int
|
||||
mpc52xx_uart_suspend(struct platform_device *dev, pm_message_t state)
|
||||
{
|
||||
struct uart_port *port = (struct uart_port *) platform_get_drvdata(dev);
|
||||
|
||||
if (port)
|
||||
uart_suspend_port(&mpc52xx_uart_driver, port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mpc52xx_uart_resume(struct platform_device *dev)
|
||||
{
|
||||
struct uart_port *port = (struct uart_port *) platform_get_drvdata(dev);
|
||||
|
||||
if (port)
|
||||
uart_resume_port(&mpc52xx_uart_driver, port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* work with hotplug and coldplug */
|
||||
MODULE_ALIAS("platform:mpc52xx-psc");
|
||||
|
||||
static struct platform_driver mpc52xx_uart_platform_driver = {
|
||||
.probe = mpc52xx_uart_probe,
|
||||
.remove = mpc52xx_uart_remove,
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = mpc52xx_uart_suspend,
|
||||
.resume = mpc52xx_uart_resume,
|
||||
#endif
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "mpc52xx-psc",
|
||||
},
|
||||
};
|
||||
#endif /* !defined(CONFIG_PPC_MERGE) */
|
||||
|
||||
|
||||
#if defined(CONFIG_PPC_MERGE)
|
||||
/* ======================================================================== */
|
||||
/* OF Platform Driver */
|
||||
/* ======================================================================== */
|
||||
|
|
@ -1402,7 +1239,6 @@ static struct of_platform_driver mpc52xx_uart_of_driver = {
|
|||
.name = "mpc52xx-psc-uart",
|
||||
},
|
||||
};
|
||||
#endif /* defined(CONFIG_PPC_MERGE) */
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
|
|
@ -1423,7 +1259,6 @@ mpc52xx_uart_init(void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_PPC_MERGE)
|
||||
mpc52xx_uart_of_enumerate();
|
||||
|
||||
ret = of_register_platform_driver(&mpc52xx_uart_of_driver);
|
||||
|
|
@ -1433,16 +1268,6 @@ mpc52xx_uart_init(void)
|
|||
uart_unregister_driver(&mpc52xx_uart_driver);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
psc_ops = &mpc52xx_psc_ops;
|
||||
ret = platform_driver_register(&mpc52xx_uart_platform_driver);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "%s: platform_driver_register failed (%i)\n",
|
||||
__FILE__, ret);
|
||||
uart_unregister_driver(&mpc52xx_uart_driver);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1450,11 +1275,7 @@ mpc52xx_uart_init(void)
|
|||
static void __exit
|
||||
mpc52xx_uart_exit(void)
|
||||
{
|
||||
#if defined(CONFIG_PPC_MERGE)
|
||||
of_unregister_platform_driver(&mpc52xx_uart_of_driver);
|
||||
#else
|
||||
platform_driver_unregister(&mpc52xx_uart_platform_driver);
|
||||
#endif
|
||||
uart_unregister_driver(&mpc52xx_uart_driver);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1009,7 +1009,7 @@ static int qe_uart_request_port(struct uart_port *port)
|
|||
rx_size = L1_CACHE_ALIGN(qe_port->rx_nrfifos * qe_port->rx_fifosize);
|
||||
tx_size = L1_CACHE_ALIGN(qe_port->tx_nrfifos * qe_port->tx_fifosize);
|
||||
|
||||
bd_virt = dma_alloc_coherent(NULL, rx_size + tx_size, &bd_dma_addr,
|
||||
bd_virt = dma_alloc_coherent(port->dev, rx_size + tx_size, &bd_dma_addr,
|
||||
GFP_KERNEL);
|
||||
if (!bd_virt) {
|
||||
dev_err(port->dev, "could not allocate buffer descriptors\n");
|
||||
|
|
@ -1051,7 +1051,7 @@ static void qe_uart_release_port(struct uart_port *port)
|
|||
container_of(port, struct uart_qe_port, port);
|
||||
struct ucc_slow_private *uccs = qe_port->us_private;
|
||||
|
||||
dma_free_coherent(NULL, qe_port->bd_size, qe_port->bd_virt,
|
||||
dma_free_coherent(port->dev, qe_port->bd_size, qe_port->bd_virt,
|
||||
qe_port->bd_dma_addr);
|
||||
|
||||
ucc_slow_free(uccs);
|
||||
|
|
|
|||
|
|
@ -108,13 +108,13 @@ static void mpc52xx_psc_spi_activate_cs(struct spi_device *spi)
|
|||
* Because psc->ccr is defined as 16bit register instead of 32bit
|
||||
* just set the lower byte of BitClkDiv
|
||||
*/
|
||||
ccr = in_be16(&psc->ccr);
|
||||
ccr = in_be16((u16 __iomem *)&psc->ccr);
|
||||
ccr &= 0xFF00;
|
||||
if (cs->speed_hz)
|
||||
ccr |= (MCLK / cs->speed_hz - 1) & 0xFF;
|
||||
else /* by default SPI Clk 1MHz */
|
||||
ccr |= (MCLK / 1000000 - 1) & 0xFF;
|
||||
out_be16(&psc->ccr, ccr);
|
||||
out_be16((u16 __iomem *)&psc->ccr, ccr);
|
||||
mps->bits_per_word = cs->bits_per_word;
|
||||
|
||||
if (mps->activate_cs)
|
||||
|
|
@ -347,7 +347,7 @@ static int mpc52xx_psc_spi_port_config(int psc_id, struct mpc52xx_psc_spi *mps)
|
|||
/* Configure 8bit codec mode as a SPI master and use EOF flags */
|
||||
/* SICR_SIM_CODEC8|SICR_GENCLK|SICR_SPI|SICR_MSTR|SICR_USEEOF */
|
||||
out_be32(&psc->sicr, 0x0180C800);
|
||||
out_be16(&psc->ccr, 0x070F); /* by default SPI Clk 1MHz */
|
||||
out_be16((u16 __iomem *)&psc->ccr, 0x070F); /* default SPI Clk 1MHz */
|
||||
|
||||
/* Set 2ms DTL delay */
|
||||
out_8(&psc->ctur, 0x00);
|
||||
|
|
|
|||
Loading…
Reference in a new issue