aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/i2c/busses/i2c-pmac-smu.c17
-rw-r--r--drivers/macintosh/smu.c58
-rw-r--r--drivers/macintosh/via-pmu.c264
3 files changed, 51 insertions, 288 deletions
diff --git a/drivers/i2c/busses/i2c-pmac-smu.c b/drivers/i2c/busses/i2c-pmac-smu.c
index bfefe7f..7d925be 100644
--- a/drivers/i2c/busses/i2c-pmac-smu.c
+++ b/drivers/i2c/busses/i2c-pmac-smu.c
@@ -103,8 +103,8 @@ static s32 smu_smbus_xfer( struct i2c_adapter* adap,
cmd.info.subaddr[1] = 0;
cmd.info.subaddr[2] = 0;
if (!read) {
- cmd.info.data[0] = data->byte & 0xff;
- cmd.info.data[1] = (data->byte >> 8) & 0xff;
+ cmd.info.data[0] = data->word & 0xff;
+ cmd.info.data[1] = (data->word >> 8) & 0xff;
}
break;
/* Note that these are broken vs. the expected smbus API where
@@ -116,7 +116,7 @@ static s32 smu_smbus_xfer( struct i2c_adapter* adap,
case I2C_SMBUS_BLOCK_DATA:
cmd.info.type = SMU_I2C_TRANSFER_STDSUB;
cmd.info.datalen = data->block[0] + 1;
- if (cmd.info.datalen > 6)
+ if (cmd.info.datalen > (SMU_I2C_WRITE_MAX + 1))
return -EINVAL;
if (!read)
memcpy(cmd.info.data, data->block, cmd.info.datalen);
@@ -273,7 +273,13 @@ static int dispose_iface(struct device *dev)
static int create_iface_of_platform(struct of_device* dev,
const struct of_device_id *match)
{
- return create_iface(dev->node, &dev->dev);
+ struct device_node *node = dev->node;
+
+ if (device_is_compatible(node, "smu-i2c") ||
+ (node->parent != NULL &&
+ device_is_compatible(node->parent, "smu-i2c-control")))
+ return create_iface(node, &dev->dev);
+ return -ENODEV;
}
@@ -288,6 +294,9 @@ static struct of_device_id i2c_smu_match[] =
{
.compatible = "smu-i2c",
},
+ {
+ .compatible = "i2c-bus",
+ },
{},
};
static struct of_platform_driver i2c_smu_of_platform_driver =
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c
index 9622611..9ecd768 100644
--- a/drivers/macintosh/smu.c
+++ b/drivers/macintosh/smu.c
@@ -94,6 +94,8 @@ struct smu_device {
static struct smu_device *smu;
static DECLARE_MUTEX(smu_part_access);
+static void smu_i2c_retry(unsigned long data);
+
/*
* SMU driver low level stuff
*/
@@ -469,7 +471,6 @@ int __init smu_init (void)
smu->of_node = np;
smu->db_irq = NO_IRQ;
smu->msg_irq = NO_IRQ;
- init_timer(&smu->i2c_timer);
/* smu_cmdbuf_abs is in the low 2G of RAM, can be converted to a
* 32 bits value safely
@@ -544,6 +545,10 @@ static int smu_late_init(void)
if (!smu)
return 0;
+ init_timer(&smu->i2c_timer);
+ smu->i2c_timer.function = smu_i2c_retry;
+ smu->i2c_timer.data = (unsigned long)smu;
+
/*
* Try to request the interrupts
*/
@@ -570,28 +575,41 @@ static int smu_late_init(void)
return 0;
}
-arch_initcall(smu_late_init);
+/* This has to be before arch_initcall as the low i2c stuff relies on the
+ * above having been done before we reach arch_initcalls
+ */
+core_initcall(smu_late_init);
/*
* sysfs visibility
*/
+static void smu_create_i2c(struct device_node *np)
+{
+ char name[32];
+ u32 *reg = (u32 *)get_property(np, "reg", NULL);
+
+ if (reg != NULL) {
+ sprintf(name, "smu-i2c-%02x", *reg);
+ of_platform_device_create(np, name, &smu->of_dev->dev);
+ }
+}
+
static void smu_expose_childs(void *unused)
{
- struct device_node *np;
+ struct device_node *np, *gp;
for (np = NULL; (np = of_get_next_child(smu->of_node, np)) != NULL;) {
- if (device_is_compatible(np, "smu-i2c")) {
- char name[32];
- u32 *reg = (u32 *)get_property(np, "reg", NULL);
-
- if (reg == NULL)
- continue;
- sprintf(name, "smu-i2c-%02x", *reg);
- of_platform_device_create(np, name, &smu->of_dev->dev);
- }
+ if (device_is_compatible(np, "smu-i2c-control")) {
+ gp = NULL;
+ while ((gp = of_get_next_child(np, gp)) != NULL)
+ if (device_is_compatible(gp, "i2c-bus"))
+ smu_create_i2c(gp);
+ } else if (device_is_compatible(np, "smu-i2c"))
+ smu_create_i2c(np);
if (device_is_compatible(np, "smu-sensors"))
- of_platform_device_create(np, "smu-sensors", &smu->of_dev->dev);
+ of_platform_device_create(np, "smu-sensors",
+ &smu->of_dev->dev);
}
}
@@ -712,13 +730,13 @@ static void smu_i2c_complete_command(struct smu_i2c_cmd *cmd, int fail)
static void smu_i2c_retry(unsigned long data)
{
- struct smu_i2c_cmd *cmd = (struct smu_i2c_cmd *)data;
+ struct smu_i2c_cmd *cmd = smu->cmd_i2c_cur;
DPRINTK("SMU: i2c failure, requeuing...\n");
/* requeue command simply by resetting reply_len */
cmd->pdata[0] = 0xff;
- cmd->scmd.reply_len = 0x10;
+ cmd->scmd.reply_len = sizeof(cmd->pdata);
smu_queue_cmd(&cmd->scmd);
}
@@ -747,10 +765,8 @@ static void smu_i2c_low_completion(struct smu_cmd *scmd, void *misc)
*/
if (fail && --cmd->retries > 0) {
DPRINTK("SMU: i2c failure, starting timer...\n");
- smu->i2c_timer.function = smu_i2c_retry;
- smu->i2c_timer.data = (unsigned long)cmd;
- smu->i2c_timer.expires = jiffies + msecs_to_jiffies(5);
- add_timer(&smu->i2c_timer);
+ BUG_ON(cmd != smu->cmd_i2c_cur);
+ mod_timer(&smu->i2c_timer, jiffies + msecs_to_jiffies(5));
return;
}
@@ -764,7 +780,7 @@ static void smu_i2c_low_completion(struct smu_cmd *scmd, void *misc)
/* Ok, initial command complete, now poll status */
scmd->reply_buf = cmd->pdata;
- scmd->reply_len = 0x10;
+ scmd->reply_len = sizeof(cmd->pdata);
scmd->data_buf = cmd->pdata;
scmd->data_len = 1;
cmd->pdata[0] = 0;
@@ -786,7 +802,7 @@ int smu_queue_i2c(struct smu_i2c_cmd *cmd)
cmd->scmd.done = smu_i2c_low_completion;
cmd->scmd.misc = cmd;
cmd->scmd.reply_buf = cmd->pdata;
- cmd->scmd.reply_len = 0x10;
+ cmd->scmd.reply_len = sizeof(cmd->pdata);
cmd->scmd.data_buf = (u8 *)(char *)&cmd->info;
cmd->scmd.status = 1;
cmd->stage = 0;
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 3c05520..aa481a8 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -197,7 +197,6 @@ static int pmu_adb_reset_bus(void);
#endif /* CONFIG_ADB */
static int init_pmu(void);
-static int pmu_queue_request(struct adb_request *req);
static void pmu_start(void);
static irqreturn_t via_pmu_interrupt(int irq, void *arg, struct pt_regs *regs);
static irqreturn_t gpio1_interrupt(int irq, void *arg, struct pt_regs *regs);
@@ -1802,258 +1801,6 @@ pmu_present(void)
return via != 0;
}
-struct pmu_i2c_hdr {
- u8 bus;
- u8 mode;
- u8 bus2;
- u8 address;
- u8 sub_addr;
- u8 comb_addr;
- u8 count;
-};
-
-int
-pmu_i2c_combined_read(int bus, int addr, int subaddr, u8* data, int len)
-{
- struct adb_request req;
- struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req.data[1];
- int retry;
- int rc;
-
- for (retry=0; retry<16; retry++) {
- memset(&req, 0, sizeof(req));
-
- hdr->bus = bus;
- hdr->address = addr & 0xfe;
- hdr->mode = PMU_I2C_MODE_COMBINED;
- hdr->bus2 = 0;
- hdr->sub_addr = subaddr;
- hdr->comb_addr = addr | 1;
- hdr->count = len;
-
- req.nbytes = sizeof(struct pmu_i2c_hdr) + 1;
- req.reply_expected = 0;
- req.reply_len = 0;
- req.data[0] = PMU_I2C_CMD;
- req.reply[0] = 0xff;
- rc = pmu_queue_request(&req);
- if (rc)
- return rc;
- while(!req.complete)
- pmu_poll();
- if (req.reply[0] == PMU_I2C_STATUS_OK)
- break;
- mdelay(15);
- }
- if (req.reply[0] != PMU_I2C_STATUS_OK)
- return -1;
-
- for (retry=0; retry<16; retry++) {
- memset(&req, 0, sizeof(req));
-
- mdelay(15);
-
- hdr->bus = PMU_I2C_BUS_STATUS;
- req.reply[0] = 0xff;
-
- req.nbytes = 2;
- req.reply_expected = 0;
- req.reply_len = 0;
- req.data[0] = PMU_I2C_CMD;
- rc = pmu_queue_request(&req);
- if (rc)
- return rc;
- while(!req.complete)
- pmu_poll();
- if (req.reply[0] == PMU_I2C_STATUS_DATAREAD) {
- memcpy(data, &req.reply[1], req.reply_len - 1);
- return req.reply_len - 1;
- }
- }
- return -1;
-}
-
-int
-pmu_i2c_stdsub_write(int bus, int addr, int subaddr, u8* data, int len)
-{
- struct adb_request req;
- struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req.data[1];
- int retry;
- int rc;
-
- for (retry=0; retry<16; retry++) {
- memset(&req, 0, sizeof(req));
-
- hdr->bus = bus;
- hdr->address = addr & 0xfe;
- hdr->mode = PMU_I2C_MODE_STDSUB;
- hdr->bus2 = 0;
- hdr->sub_addr = subaddr;
- hdr->comb_addr = addr & 0xfe;
- hdr->count = len;
-
- req.data[0] = PMU_I2C_CMD;
- memcpy(&req.data[sizeof(struct pmu_i2c_hdr) + 1], data, len);
- req.nbytes = sizeof(struct pmu_i2c_hdr) + len + 1;
- req.reply_expected = 0;
- req.reply_len = 0;
- req.reply[0] = 0xff;
- rc = pmu_queue_request(&req);
- if (rc)
- return rc;
- while(!req.complete)
- pmu_poll();
- if (req.reply[0] == PMU_I2C_STATUS_OK)
- break;
- mdelay(15);
- }
- if (req.reply[0] != PMU_I2C_STATUS_OK)
- return -1;
-
- for (retry=0; retry<16; retry++) {
- memset(&req, 0, sizeof(req));
-
- mdelay(15);
-
- hdr->bus = PMU_I2C_BUS_STATUS;
- req.reply[0] = 0xff;
-
- req.nbytes = 2;
- req.reply_expected = 0;
- req.reply_len = 0;
- req.data[0] = PMU_I2C_CMD;
- rc = pmu_queue_request(&req);
- if (rc)
- return rc;
- while(!req.complete)
- pmu_poll();
- if (req.reply[0] == PMU_I2C_STATUS_OK)
- return len;
- }
- return -1;
-}
-
-int
-pmu_i2c_simple_read(int bus, int addr, u8* data, int len)
-{
- struct adb_request req;
- struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req.data[1];
- int retry;
- int rc;
-
- for (retry=0; retry<16; retry++) {
- memset(&req, 0, sizeof(req));
-
- hdr->bus = bus;
- hdr->address = addr | 1;
- hdr->mode = PMU_I2C_MODE_SIMPLE;
- hdr->bus2 = 0;
- hdr->sub_addr = 0;
- hdr->comb_addr = 0;
- hdr->count = len;
-
- req.data[0] = PMU_I2C_CMD;
- req.nbytes = sizeof(struct pmu_i2c_hdr) + 1;
- req.reply_expected = 0;
- req.reply_len = 0;
- req.reply[0] = 0xff;
- rc = pmu_queue_request(&req);
- if (rc)
- return rc;
- while(!req.complete)
- pmu_poll();
- if (req.reply[0] == PMU_I2C_STATUS_OK)
- break;
- mdelay(15);
- }
- if (req.reply[0] != PMU_I2C_STATUS_OK)
- return -1;
-
- for (retry=0; retry<16; retry++) {
- memset(&req, 0, sizeof(req));
-
- mdelay(15);
-
- hdr->bus = PMU_I2C_BUS_STATUS;
- req.reply[0] = 0xff;
-
- req.nbytes = 2;
- req.reply_expected = 0;
- req.reply_len = 0;
- req.data[0] = PMU_I2C_CMD;
- rc = pmu_queue_request(&req);
- if (rc)
- return rc;
- while(!req.complete)
- pmu_poll();
- if (req.reply[0] == PMU_I2C_STATUS_DATAREAD) {
- memcpy(data, &req.reply[1], req.reply_len - 1);
- return req.reply_len - 1;
- }
- }
- return -1;
-}
-
-int
-pmu_i2c_simple_write(int bus, int addr, u8* data, int len)
-{
- struct adb_request req;
- struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req.data[1];
- int retry;
- int rc;
-
- for (retry=0; retry<16; retry++) {
- memset(&req, 0, sizeof(req));
-
- hdr->bus = bus;
- hdr->address = addr & 0xfe;
- hdr->mode = PMU_I2C_MODE_SIMPLE;
- hdr->bus2 = 0;
- hdr->sub_addr = 0;
- hdr->comb_addr = 0;
- hdr->count = len;
-
- req.data[0] = PMU_I2C_CMD;
- memcpy(&req.data[sizeof(struct pmu_i2c_hdr) + 1], data, len);
- req.nbytes = sizeof(struct pmu_i2c_hdr) + len + 1;
- req.reply_expected = 0;
- req.reply_len = 0;
- req.reply[0] = 0xff;
- rc = pmu_queue_request(&req);
- if (rc)
- return rc;
- while(!req.complete)
- pmu_poll();
- if (req.reply[0] == PMU_I2C_STATUS_OK)
- break;
- mdelay(15);
- }
- if (req.reply[0] != PMU_I2C_STATUS_OK)
- return -1;
-
- for (retry=0; retry<16; retry++) {
- memset(&req, 0, sizeof(req));
-
- mdelay(15);
-
- hdr->bus = PMU_I2C_BUS_STATUS;
- req.reply[0] = 0xff;
-
- req.nbytes = 2;
- req.reply_expected = 0;
- req.reply_len = 0;
- req.data[0] = PMU_I2C_CMD;
- rc = pmu_queue_request(&req);
- if (rc)
- return rc;
- while(!req.complete)
- pmu_poll();
- if (req.reply[0] == PMU_I2C_STATUS_OK)
- return len;
- }
- return -1;
-}
-
#ifdef CONFIG_PM
static LIST_HEAD(sleep_notifiers);
@@ -2358,9 +2105,6 @@ pmac_suspend_devices(void)
return -EBUSY;
}
- /* Disable clock spreading on some machines */
- pmac_tweak_clock_spreading(0);
-
/* Stop preemption */
preempt_disable();
@@ -2431,9 +2175,6 @@ pmac_wakeup_devices(void)
mdelay(10);
preempt_enable();
- /* Re-enable clock spreading on some machines */
- pmac_tweak_clock_spreading(1);
-
/* Resume devices */
device_resume();
@@ -3150,16 +2891,13 @@ static int __init init_pmu_sysfs(void)
subsys_initcall(init_pmu_sysfs);
EXPORT_SYMBOL(pmu_request);
+EXPORT_SYMBOL(pmu_queue_request);
EXPORT_SYMBOL(pmu_poll);
EXPORT_SYMBOL(pmu_poll_adb);
EXPORT_SYMBOL(pmu_wait_complete);
EXPORT_SYMBOL(pmu_suspend);
EXPORT_SYMBOL(pmu_resume);
EXPORT_SYMBOL(pmu_unlock);
-EXPORT_SYMBOL(pmu_i2c_combined_read);
-EXPORT_SYMBOL(pmu_i2c_stdsub_write);
-EXPORT_SYMBOL(pmu_i2c_simple_read);
-EXPORT_SYMBOL(pmu_i2c_simple_write);
#if defined(CONFIG_PM) && defined(CONFIG_PPC32)
EXPORT_SYMBOL(pmu_enable_irled);
EXPORT_SYMBOL(pmu_battery_count);