From 99ca177ae4d31c3fbbea7ffb213b9724e4c26233 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 14 Oct 2009 05:31:32 +0000 Subject: powerpc/therm_adt746x: Don't access non-existing register The ADT746x don't have any register at sub-address 0, so better use an existing register for the initial test read. Signed-off-by: Jean Delvare Cc: Colin Leroy Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Signed-off-by: Benjamin Herrenschmidt --- drivers/macintosh/therm_adt746x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/macintosh') diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c index 556f0feaa4df..95b676a19be7 100644 --- a/drivers/macintosh/therm_adt746x.c +++ b/drivers/macintosh/therm_adt746x.c @@ -387,7 +387,7 @@ static int probe_thermostat(struct i2c_client *client, i2c_set_clientdata(client, th); th->clt = client; - rc = read_reg(th, 0); + rc = read_reg(th, CONFIG_REG); if (rc < 0) { dev_err(&client->dev, "Thermostat failed to read config!\n"); kfree(th); -- cgit v1.2.3-59-g8ed1b From 0b048c7a1d7f65e3e3f77834c03237be9d6d94b7 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 15 Oct 2009 10:28:38 +0000 Subject: macintosh: Remove BKL from nvram driver Drop the bkl from nvram_llseek() as it obviously protects nothing. The file offset is safe in essence. The ioctl can be converted to unlocked_ioctl because it just calls pmac_get_partition() which reads a value from an array which was initialized at early boot time. No need for serialization. Signed-off-by: Thomas Gleixner Cc: Benjamin Herrenschmidt Cc: linuxppc-dev@ozlabs.org Signed-off-by: Benjamin Herrenschmidt --- drivers/macintosh/nvram.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers/macintosh') diff --git a/drivers/macintosh/nvram.c b/drivers/macintosh/nvram.c index b195d753d2ed..c876349c32de 100644 --- a/drivers/macintosh/nvram.c +++ b/drivers/macintosh/nvram.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include @@ -21,7 +20,6 @@ static loff_t nvram_llseek(struct file *file, loff_t offset, int origin) { - lock_kernel(); switch (origin) { case 1: offset += file->f_pos; @@ -30,12 +28,10 @@ static loff_t nvram_llseek(struct file *file, loff_t offset, int origin) offset += NVRAM_SIZE; break; } - if (offset < 0) { - unlock_kernel(); + if (offset < 0) return -EINVAL; - } + file->f_pos = offset; - unlock_kernel(); return file->f_pos; } @@ -76,8 +72,7 @@ static ssize_t write_nvram(struct file *file, const char __user *buf, return p - buf; } -static int nvram_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long nvram_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { switch(cmd) { case PMAC_NVRAM_GET_OFFSET: -- cgit v1.2.3-59-g8ed1b From 9d2f7342d08896338890904351490739c1035d43 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Thu, 26 Nov 2009 20:53:06 +0000 Subject: powerpc/via-pmu: Convert to proc_fops/seq_file Signed-off-by: Alexey Dobriyan Signed-off-by: Benjamin Herrenschmidt --- drivers/macintosh/via-pmu.c | 160 +++++++++++++++++++++++++------------------- 1 file changed, 91 insertions(+), 69 deletions(-) (limited to 'drivers/macintosh') diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index 6f308a4757ee..db379c381432 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -186,17 +187,11 @@ static int init_pmu(void); static void pmu_start(void); static irqreturn_t via_pmu_interrupt(int irq, void *arg); static irqreturn_t gpio1_interrupt(int irq, void *arg); -static int proc_get_info(char *page, char **start, off_t off, - int count, int *eof, void *data); -static int proc_get_irqstats(char *page, char **start, off_t off, - int count, int *eof, void *data); +static const struct file_operations pmu_info_proc_fops; +static const struct file_operations pmu_irqstats_proc_fops; static void pmu_pass_intr(unsigned char *data, int len); -static int proc_get_batt(char *page, char **start, off_t off, - int count, int *eof, void *data); -static int proc_read_options(char *page, char **start, off_t off, - int count, int *eof, void *data); -static int proc_write_options(struct file *file, const char __user *buffer, - unsigned long count, void *data); +static const struct file_operations pmu_battery_proc_fops; +static const struct file_operations pmu_options_proc_fops; #ifdef CONFIG_ADB struct adb_driver via_pmu_driver = { @@ -507,19 +502,15 @@ static int __init via_pmu_dev_init(void) for (i=0; iread_proc = proc_read_options; - proc_pmu_options->write_proc = proc_write_options; - } + proc_pmu_info = proc_create("info", 0, proc_pmu_root, &pmu_info_proc_fops); + proc_pmu_irqstats = proc_create("interrupts", 0, proc_pmu_root, + &pmu_irqstats_proc_fops); + proc_pmu_options = proc_create("options", 0600, proc_pmu_root, + &pmu_options_proc_fops); } return 0; } @@ -799,27 +790,33 @@ query_battery_state(void) 2, PMU_SMART_BATTERY_STATE, pmu_cur_battery+1); } -static int -proc_get_info(char *page, char **start, off_t off, - int count, int *eof, void *data) +static int pmu_info_proc_show(struct seq_file *m, void *v) { - char* p = page; - - p += sprintf(p, "PMU driver version : %d\n", PMU_DRIVER_VERSION); - p += sprintf(p, "PMU firmware version : %02x\n", pmu_version); - p += sprintf(p, "AC Power : %d\n", + seq_printf(m, "PMU driver version : %d\n", PMU_DRIVER_VERSION); + seq_printf(m, "PMU firmware version : %02x\n", pmu_version); + seq_printf(m, "AC Power : %d\n", ((pmu_power_flags & PMU_PWR_AC_PRESENT) != 0) || pmu_battery_count == 0); - p += sprintf(p, "Battery count : %d\n", pmu_battery_count); + seq_printf(m, "Battery count : %d\n", pmu_battery_count); + + return 0; +} - return p - page; +static int pmu_info_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, pmu_info_proc_show, NULL); } -static int -proc_get_irqstats(char *page, char **start, off_t off, - int count, int *eof, void *data) +static const struct file_operations pmu_info_proc_fops = { + .owner = THIS_MODULE, + .open = pmu_info_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int pmu_irqstats_proc_show(struct seq_file *m, void *v) { int i; - char* p = page; static const char *irq_names[] = { "Total CB1 triggered events", "Total GPIO1 triggered events", @@ -835,60 +832,76 @@ proc_get_irqstats(char *page, char **start, off_t off, }; for (i=0; i<11; i++) { - p += sprintf(p, " %2u: %10u (%s)\n", + seq_printf(m, " %2u: %10u (%s)\n", i, pmu_irq_stats[i], irq_names[i]); } - return p - page; + return 0; } -static int -proc_get_batt(char *page, char **start, off_t off, - int count, int *eof, void *data) +static int pmu_irqstats_proc_open(struct inode *inode, struct file *file) { - long batnum = (long)data; - char *p = page; + return single_open(file, pmu_irqstats_proc_show, NULL); +} + +static const struct file_operations pmu_irqstats_proc_fops = { + .owner = THIS_MODULE, + .open = pmu_irqstats_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int pmu_battery_proc_show(struct seq_file *m, void *v) +{ + long batnum = (long)m->private; - p += sprintf(p, "\n"); - p += sprintf(p, "flags : %08x\n", - pmu_batteries[batnum].flags); - p += sprintf(p, "charge : %d\n", - pmu_batteries[batnum].charge); - p += sprintf(p, "max_charge : %d\n", - pmu_batteries[batnum].max_charge); - p += sprintf(p, "current : %d\n", - pmu_batteries[batnum].amperage); - p += sprintf(p, "voltage : %d\n", - pmu_batteries[batnum].voltage); - p += sprintf(p, "time rem. : %d\n", - pmu_batteries[batnum].time_remaining); - - return p - page; + seq_putc(m, '\n'); + seq_printf(m, "flags : %08x\n", pmu_batteries[batnum].flags); + seq_printf(m, "charge : %d\n", pmu_batteries[batnum].charge); + seq_printf(m, "max_charge : %d\n", pmu_batteries[batnum].max_charge); + seq_printf(m, "current : %d\n", pmu_batteries[batnum].amperage); + seq_printf(m, "voltage : %d\n", pmu_batteries[batnum].voltage); + seq_printf(m, "time rem. : %d\n", pmu_batteries[batnum].time_remaining); + return 0; } -static int -proc_read_options(char *page, char **start, off_t off, - int count, int *eof, void *data) +static int pmu_battery_proc_open(struct inode *inode, struct file *file) { - char *p = page; + return single_open(file, pmu_battery_proc_show, PDE(inode)->data); +} +static const struct file_operations pmu_battery_proc_fops = { + .owner = THIS_MODULE, + .open = pmu_battery_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int pmu_options_proc_show(struct seq_file *m, void *v) +{ #if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32) if (pmu_kind == PMU_KEYLARGO_BASED && pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0) - p += sprintf(p, "lid_wakeup=%d\n", option_lid_wakeup); + seq_printf(m, "lid_wakeup=%d\n", option_lid_wakeup); #endif if (pmu_kind == PMU_KEYLARGO_BASED) - p += sprintf(p, "server_mode=%d\n", option_server_mode); + seq_printf(m, "server_mode=%d\n", option_server_mode); - return p - page; + return 0; } - -static int -proc_write_options(struct file *file, const char __user *buffer, - unsigned long count, void *data) + +static int pmu_options_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, pmu_options_proc_show, NULL); +} + +static ssize_t pmu_options_proc_write(struct file *file, + const char __user *buffer, size_t count, loff_t *pos) { char tmp[33]; char *label, *val; - unsigned long fcount = count; + size_t fcount = count; if (!count) return -EINVAL; @@ -927,6 +940,15 @@ proc_write_options(struct file *file, const char __user *buffer, return fcount; } +static const struct file_operations pmu_options_proc_fops = { + .owner = THIS_MODULE, + .open = pmu_options_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = pmu_options_proc_write, +}; + #ifdef CONFIG_ADB /* Send an ADB command */ static int pmu_send_request(struct adb_request *req, int sync) -- cgit v1.2.3-59-g8ed1b From 529586dc39b0ec47c6290c4e7bed6ea3ffd1d8fb Mon Sep 17 00:00:00 2001 From: Bolko Maass Date: Fri, 27 Nov 2009 05:44:33 +0000 Subject: powerpc/windfarm: Add detection for second cpu pump Windfarm SMU control is explicitly missing support for a second CPU pump in G5 PowerMacs. Such machines actually exist (specifically Quads with a second pump), so this patch adds detection for it. Signed-off by: Bolko Maass CC: Signed-off-by: Benjamin Herrenschmidt --- drivers/macintosh/windfarm_smu_controls.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/macintosh') diff --git a/drivers/macintosh/windfarm_smu_controls.c b/drivers/macintosh/windfarm_smu_controls.c index 961fa0e7c2cf..6c68b9e5f5c4 100644 --- a/drivers/macintosh/windfarm_smu_controls.c +++ b/drivers/macintosh/windfarm_smu_controls.c @@ -202,6 +202,8 @@ static struct smu_fan_control *smu_fan_create(struct device_node *node, fct->ctrl.name = "cpu-front-fan-1"; else if (!strcmp(l, "CPU A PUMP")) fct->ctrl.name = "cpu-pump-0"; + else if (!strcmp(l, "CPU B PUMP")) + fct->ctrl.name = "cpu-pump-1"; else if (!strcmp(l, "Slots Fan") || !strcmp(l, "Slots fan") || !strcmp(l, "EXPANSION SLOTS INTAKE")) fct->ctrl.name = "slots-fan"; -- cgit v1.2.3-59-g8ed1b From 7fb19ea054a0cdf1a4d935e68d51bde4d3725414 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 1 Dec 2009 14:36:26 +0000 Subject: powerpc/macio: Add devres support to macio_device This adds some basic devres support. When enabled via macio_enable_devres() resources requested by drivers will be automatically released. Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/macio.h | 2 ++ drivers/macintosh/macio_asic.c | 47 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) (limited to 'drivers/macintosh') diff --git a/arch/powerpc/include/asm/macio.h b/arch/powerpc/include/asm/macio.h index 079c06eae446..2b7b39294a6a 100644 --- a/arch/powerpc/include/asm/macio.h +++ b/arch/powerpc/include/asm/macio.h @@ -78,6 +78,8 @@ static inline unsigned long macio_resource_len(struct macio_dev *dev, int resour return res->end - res->start + 1; } +extern int macio_enable_devres(struct macio_dev *dev); + extern int macio_request_resource(struct macio_dev *dev, int resource_no, const char *name); extern void macio_release_resource(struct macio_dev *dev, int resource_no); extern int macio_request_resources(struct macio_dev *dev, const char *name); diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index 588a5b0bc4b5..5200acfc9d38 100644 --- a/drivers/macintosh/macio_asic.c +++ b/drivers/macintosh/macio_asic.c @@ -538,6 +538,42 @@ void macio_unregister_driver(struct macio_driver *drv) driver_unregister(&drv->driver); } +/* Managed MacIO resources */ +struct macio_devres { + u32 res_mask; +}; + +static void maciom_release(struct device *gendev, void *res) +{ + struct macio_dev *dev = to_macio_device(gendev); + struct macio_devres *dr = res; + int i, max; + + max = min(dev->n_resources, 32); + for (i = 0; i < max; i++) { + if (dr->res_mask & (1 << i)) + macio_release_resource(dev, i); + } +} + +int macio_enable_devres(struct macio_dev *dev) +{ + struct macio_devres *dr; + + dr = devres_find(&dev->ofdev.dev, maciom_release, NULL, NULL); + if (!dr) { + dr = devres_alloc(maciom_release, sizeof(*dr), GFP_KERNEL); + if (!dr) + return -ENOMEM; + } + return devres_get(&dev->ofdev.dev, dr, NULL, NULL) != NULL; +} + +static struct macio_devres * find_macio_dr(struct macio_dev *dev) +{ + return devres_find(&dev->ofdev.dev, maciom_release, NULL, NULL); +} + /** * macio_request_resource - Request an MMIO resource * @dev: pointer to the device holding the resource @@ -555,6 +591,8 @@ void macio_unregister_driver(struct macio_driver *drv) int macio_request_resource(struct macio_dev *dev, int resource_no, const char *name) { + struct macio_devres *dr = find_macio_dr(dev); + if (macio_resource_len(dev, resource_no) == 0) return 0; @@ -562,6 +600,9 @@ int macio_request_resource(struct macio_dev *dev, int resource_no, macio_resource_len(dev, resource_no), name)) goto err_out; + + if (dr && resource_no < 32) + dr->res_mask |= 1 << resource_no; return 0; @@ -582,10 +623,14 @@ err_out: */ void macio_release_resource(struct macio_dev *dev, int resource_no) { + struct macio_devres *dr = find_macio_dr(dev); + if (macio_resource_len(dev, resource_no) == 0) return; release_mem_region(macio_resource_start(dev, resource_no), macio_resource_len(dev, resource_no)); + if (dr && resource_no < 32) + dr->res_mask &= ~(1 << resource_no); } /** @@ -744,3 +789,5 @@ EXPORT_SYMBOL(macio_request_resource); EXPORT_SYMBOL(macio_release_resource); EXPORT_SYMBOL(macio_request_resources); EXPORT_SYMBOL(macio_release_resources); +EXPORT_SYMBOL(macio_enable_devres); + -- cgit v1.2.3-59-g8ed1b From 128b4a0ef74e8d48033513e41a413087ba30e36b Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 1 Dec 2009 14:36:27 +0000 Subject: powerpc/macio: Add dma_parms support to macio This adds dma_parms to macio devices and initializes them with default values. This will allow pata_macio to setup the appropriate max segment size for the block layer. Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/macio.h | 1 + drivers/macintosh/macio_asic.c | 5 +++++ 2 files changed, 6 insertions(+) (limited to 'drivers/macintosh') diff --git a/arch/powerpc/include/asm/macio.h b/arch/powerpc/include/asm/macio.h index 2b7b39294a6a..86d5fed1c49f 100644 --- a/arch/powerpc/include/asm/macio.h +++ b/arch/powerpc/include/asm/macio.h @@ -39,6 +39,7 @@ struct macio_dev struct macio_bus *bus; /* macio bus this device is on */ struct macio_dev *media_bay; /* Device is part of a media bay */ struct of_device ofdev; + struct device_dma_parameters dma_parms; /* ide needs that */ int n_resources; struct resource resource[MACIO_DEV_COUNT_RESOURCES]; int n_interrupts; diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index 5200acfc9d38..26a303a1d1ab 100644 --- a/drivers/macintosh/macio_asic.c +++ b/drivers/macintosh/macio_asic.c @@ -379,6 +379,11 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip, dev->ofdev.dev.parent = parent; dev->ofdev.dev.bus = &macio_bus_type; dev->ofdev.dev.release = macio_release_dev; + dev->ofdev.dev.dma_parms = &dev->dma_parms; + + /* Standard DMA paremeters */ + dma_set_max_seg_size(&dev->ofdev.dev, 65536); + dma_set_seg_boundary(&dev->ofdev.dev, 0xffffffff); #ifdef CONFIG_PCI /* Set the DMA ops to the ones from the PCI device, this could be -- cgit v1.2.3-59-g8ed1b From d58b0c39e32f1b410af4d070f9d1a1416057c166 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 1 Dec 2009 14:36:28 +0000 Subject: powerpc/macio: Rework hotplug media bay support The hotplug mediabay has tendrils deep into drivers/ide code which makes a libata port reather difficult. In addition it's ugly and could be done better. This reworks the interface between the mediabay and the rest of the world so that: - Any macio_driver can now have a mediabay_event callback which will be called when that driver sits on a mediabay and it's been either plugged or unplugged. The device type is passed as an argument. We can now move all the IDE cruft into the IDE driver itself - A check_media_bay() function can be used to take a peek at the type of device currently in the bay if any, a cleaner variant of the previous function with the same name. - A pair of lock/unlock functions are exposed to allow the IDE driver to block the hotplug callbacks during the initial setup and probing of the bay in order to avoid nasty race conditions. - The mediabay code no longer needs to spin on the status register of the IDE interface when it detects an IDE device, this is done just fine by the IDE code itself Overall, less code, simpler, and allows for another driver than our old drivers/ide based one. Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/include/asm/macio.h | 3 + arch/powerpc/include/asm/mediabay.h | 27 +-- drivers/block/swim3.c | 39 ++--- drivers/ide/pmac.c | 92 ++++++---- drivers/macintosh/mediabay.c | 328 ++++++++++++++---------------------- 5 files changed, 214 insertions(+), 275 deletions(-) (limited to 'drivers/macintosh') diff --git a/arch/powerpc/include/asm/macio.h b/arch/powerpc/include/asm/macio.h index 86d5fed1c49f..a062c57696d0 100644 --- a/arch/powerpc/include/asm/macio.h +++ b/arch/powerpc/include/asm/macio.h @@ -134,6 +134,9 @@ struct macio_driver int (*resume)(struct macio_dev* dev); int (*shutdown)(struct macio_dev* dev); +#ifdef CONFIG_PMAC_MEDIABAY + void (*mediabay_event)(struct macio_dev* dev, int mb_state); +#endif struct device_driver driver; }; #define to_macio_driver(drv) container_of(drv,struct macio_driver, driver) diff --git a/arch/powerpc/include/asm/mediabay.h b/arch/powerpc/include/asm/mediabay.h index b2efb3325808..11037a4133ee 100644 --- a/arch/powerpc/include/asm/mediabay.h +++ b/arch/powerpc/include/asm/mediabay.h @@ -17,26 +17,31 @@ #define MB_POWER 6 /* media bay contains a Power device (???) */ #define MB_NO 7 /* media bay contains nothing */ -/* Number of bays in the machine or 0 */ -extern int media_bay_count; +struct macio_dev; -#ifdef CONFIG_BLK_DEV_IDE_PMAC -#include +#ifdef CONFIG_PMAC_MEDIABAY -int check_media_bay_by_base(unsigned long base, int what); -/* called by IDE PMAC host driver to register IDE controller for media bay */ -int media_bay_set_ide_infos(struct device_node *which_bay, unsigned long base, - int irq, ide_hwif_t *hwif); +/* Check the content type of the bay, returns MB_NO if the bay is still + * transitionning + */ +extern int check_media_bay(struct macio_dev *bay); -int check_media_bay(struct device_node *which_bay, int what); +/* The ATA driver uses the calls below to temporarily hold on the + * media bay callbacks while initializing the interface + */ +extern void lock_media_bay(struct macio_dev *bay); +extern void unlock_media_bay(struct macio_dev *bay); #else -static inline int check_media_bay(struct device_node *which_bay, int what) +static inline int check_media_bay(struct macio_dev *bay) { - return -ENODEV; + return MB_NO; } +static inline void lock_media_bay(struct macio_dev *bay) { } +static inline void unlock_media_bay(struct macio_dev *bay) { } + #endif #endif /* __KERNEL__ */ diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c index 6380ad8d91bd..59ca2b77b574 100644 --- a/drivers/block/swim3.c +++ b/drivers/block/swim3.c @@ -200,7 +200,7 @@ struct floppy_state { int ejected; wait_queue_head_t wait; int wanted; - struct device_node* media_bay; /* NULL when not in bay */ + struct macio_dev *mdev; char dbdma_cmd_space[5 * sizeof(struct dbdma_cmd)]; }; @@ -303,14 +303,13 @@ static int swim3_readbit(struct floppy_state *fs, int bit) static void do_fd_request(struct request_queue * q) { int i; - for(i=0;imdev->media_bay && + check_media_bay(fs->mdev->media_bay) != MB_FD) continue; -#endif /* CONFIG_PMAC_MEDIABAY */ - start_request(&floppy_states[i]); + start_request(fs); } } @@ -849,10 +848,9 @@ static int floppy_ioctl(struct block_device *bdev, fmode_t mode, if ((cmd & 0x80) && !capable(CAP_SYS_ADMIN)) return -EPERM; -#ifdef CONFIG_PMAC_MEDIABAY - if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD)) + if (fs->mdev->media_bay && + check_media_bay(fs->mdev->media_bay) != MB_FD) return -ENXIO; -#endif switch (cmd) { case FDEJECT: @@ -876,10 +874,9 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) int n, err = 0; if (fs->ref_count == 0) { -#ifdef CONFIG_PMAC_MEDIABAY - if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD)) + if (fs->mdev->media_bay && + check_media_bay(fs->mdev->media_bay) != MB_FD) return -ENXIO; -#endif out_8(&sw->setup, S_IBM_DRIVE | S_FCLK_DIV2); out_8(&sw->control_bic, 0xff); out_8(&sw->mode, 0x95); @@ -963,10 +960,9 @@ static int floppy_revalidate(struct gendisk *disk) struct swim3 __iomem *sw; int ret, n; -#ifdef CONFIG_PMAC_MEDIABAY - if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD)) + if (fs->mdev->media_bay && + check_media_bay(fs->mdev->media_bay) != MB_FD) return -ENXIO; -#endif sw = fs->swim3; grab_drive(fs, revalidating, 0); @@ -1009,7 +1005,6 @@ static const struct block_device_operations floppy_fops = { static int swim3_add_device(struct macio_dev *mdev, int index) { struct device_node *swim = mdev->ofdev.node; - struct device_node *mediabay; struct floppy_state *fs = &floppy_states[index]; int rc = -EBUSY; @@ -1036,9 +1031,7 @@ static int swim3_add_device(struct macio_dev *mdev, int index) } dev_set_drvdata(&mdev->ofdev.dev, fs); - mediabay = (strcasecmp(swim->parent->type, "media-bay") == 0) ? - swim->parent : NULL; - if (mediabay == NULL) + if (mdev->media_bay == NULL) pmac_call_feature(PMAC_FTR_SWIM3_ENABLE, swim, 0, 1); memset(fs, 0, sizeof(*fs)); @@ -1068,7 +1061,7 @@ static int swim3_add_device(struct macio_dev *mdev, int index) fs->secpercyl = 36; fs->secpertrack = 18; fs->total_secs = 2880; - fs->media_bay = mediabay; + fs->mdev = mdev; init_waitqueue_head(&fs->wait); fs->dma_cmd = (struct dbdma_cmd *) DBDMA_ALIGN(fs->dbdma_cmd_space); @@ -1093,7 +1086,7 @@ static int swim3_add_device(struct macio_dev *mdev, int index) init_timer(&fs->timeout); printk(KERN_INFO "fd%d: SWIM3 floppy controller %s\n", floppy_count, - mediabay ? "in media bay" : ""); + mdev->media_bay ? "in media bay" : ""); return 0; diff --git a/drivers/ide/pmac.c b/drivers/ide/pmac.c index 97642a7a79c4..7a4e788cab2f 100644 --- a/drivers/ide/pmac.c +++ b/drivers/ide/pmac.c @@ -43,10 +43,7 @@ #include #include #include - -#ifndef CONFIG_PPC64 #include -#endif #define DRV_NAME "ide-pmac" @@ -59,13 +56,14 @@ typedef struct pmac_ide_hwif { int irq; int kind; int aapl_bus_id; - unsigned mediabay : 1; unsigned broken_dma : 1; unsigned broken_dma_warn : 1; struct device_node* node; struct macio_dev *mdev; u32 timings[4]; volatile u32 __iomem * *kauai_fcr; + ide_hwif_t *hwif; + /* Those fields are duplicating what is in hwif. We currently * can't use the hwif ones because of some assumptions that are * beeing done by the generic code about the kind of dma controller @@ -854,6 +852,11 @@ sanitize_timings(pmac_ide_hwif_t *pmif) pmif->timings[2] = pmif->timings[3] = value2; } +static int on_media_bay(pmac_ide_hwif_t *pmif) +{ + return pmif->mdev && pmif->mdev->media_bay != NULL; +} + /* Suspend call back, should be called after the child devices * have actually been suspended */ @@ -866,7 +869,7 @@ static int pmac_ide_do_suspend(pmac_ide_hwif_t *pmif) disable_irq(pmif->irq); /* The media bay will handle itself just fine */ - if (pmif->mediabay) + if (on_media_bay(pmif)) return 0; /* Kauai has bus control FCRs directly here */ @@ -889,7 +892,7 @@ static int pmac_ide_do_suspend(pmac_ide_hwif_t *pmif) static int pmac_ide_do_resume(pmac_ide_hwif_t *pmif) { /* Hard reset & re-enable controller (do we really need to reset ? -BenH) */ - if (!pmif->mediabay) { + if (!on_media_bay(pmif)) { ppc_md.feature_call(PMAC_FTR_IDE_RESET, pmif->node, pmif->aapl_bus_id, 1); ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, pmif->node, pmif->aapl_bus_id, 1); msleep(10); @@ -950,13 +953,11 @@ static void pmac_ide_init_dev(ide_drive_t *drive) pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); - if (pmif->mediabay) { -#ifdef CONFIG_PMAC_MEDIABAY - if (check_media_bay_by_base(pmif->regbase, MB_CD) == 0) { + if (on_media_bay(pmif)) { + if (check_media_bay(pmif->mdev->media_bay) == MB_CD) { drive->dev_flags &= ~IDE_DFLAG_NOPROBE; return; } -#endif drive->dev_flags |= IDE_DFLAG_NOPROBE; } } @@ -1072,26 +1073,23 @@ static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, writel(KAUAI_FCR_UATA_MAGIC | KAUAI_FCR_UATA_RESET_N | KAUAI_FCR_UATA_ENABLE, pmif->kauai_fcr); - - pmif->mediabay = 0; /* Make sure we have sane timings */ sanitize_timings(pmif); + /* If we are on a media bay, wait for it to settle and lock it */ + if (pmif->mdev) + lock_media_bay(pmif->mdev->media_bay); + host = ide_host_alloc(&d, hws, 1); - if (host == NULL) - return -ENOMEM; - hwif = host->ports[0]; + if (host == NULL) { + rc = -ENOMEM; + goto bail; + } + hwif = pmif->hwif = host->ports[0]; -#ifndef CONFIG_PPC64 - /* XXX FIXME: Media bay stuff need re-organizing */ - if (np->parent && np->parent->name - && strcasecmp(np->parent->name, "media-bay") == 0) { -#ifdef CONFIG_PMAC_MEDIABAY - media_bay_set_ide_infos(np->parent, pmif->regbase, pmif->irq, - hwif); -#endif /* CONFIG_PMAC_MEDIABAY */ - pmif->mediabay = 1; + if (on_media_bay(pmif)) { + /* Fixup bus ID for media bay */ if (!bidp) pmif->aapl_bus_id = 1; } else if (pmif->kind == controller_ohare) { @@ -1100,9 +1098,7 @@ static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, * units, I keep the old way */ ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, 0, 1); - } else -#endif - { + } else { /* This is necessary to enable IDE when net-booting */ ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 1); ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmif->aapl_bus_id, 1); @@ -1112,17 +1108,21 @@ static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, } printk(KERN_INFO DRV_NAME ": Found Apple %s controller (%s), " - "bus ID %d%s, irq %d\n", model_name[pmif->kind], - pmif->mdev ? "macio" : "PCI", pmif->aapl_bus_id, - pmif->mediabay ? " (mediabay)" : "", hw->irq); + "bus ID %d%s, irq %d\n", model_name[pmif->kind], + pmif->mdev ? "macio" : "PCI", pmif->aapl_bus_id, + on_media_bay(pmif) ? " (mediabay)" : "", hw->irq); rc = ide_host_register(host, &d, hws); - if (rc) { - ide_host_free(host); - return rc; - } + if (rc) + pmif->hwif = NULL; - return 0; + if (pmif->mdev) + unlock_media_bay(pmif->mdev->media_bay); + + bail: + if (rc && host) + ide_host_free(host); + return rc; } static void __devinit pmac_ide_init_ports(struct ide_hw *hw, unsigned long base) @@ -1362,6 +1362,25 @@ pmac_ide_pci_resume(struct pci_dev *pdev) return rc; } +#ifdef CONFIG_PMAC_MEDIABAY +static void pmac_ide_macio_mb_event(struct macio_dev* mdev, int mb_state) +{ + pmac_ide_hwif_t *pmif = + (pmac_ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev); + + switch(mb_state) { + case MB_CD: + if (!pmif->hwif->present) + ide_port_scan(pmif->hwif); + break; + default: + if (pmif->hwif->present) + ide_port_unregister_devices(pmif->hwif); + } +} +#endif /* CONFIG_PMAC_MEDIABAY */ + + static struct of_device_id pmac_ide_macio_match[] = { { @@ -1386,6 +1405,9 @@ static struct macio_driver pmac_ide_macio_driver = .probe = pmac_ide_macio_attach, .suspend = pmac_ide_macio_suspend, .resume = pmac_ide_macio_resume, +#ifdef CONFIG_PMAC_MEDIABAY + .mediabay_event = pmac_ide_macio_mb_event, +#endif }; static const struct pci_device_id pmac_ide_pci_match[] = { diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c index 029ad8ce8a7e..08002b88f342 100644 --- a/drivers/macintosh/mediabay.c +++ b/drivers/macintosh/mediabay.c @@ -33,15 +33,6 @@ #include #include - -#define MB_DEBUG - -#ifdef MB_DEBUG -#define MBDBG(fmt, arg...) printk(KERN_INFO fmt , ## arg) -#else -#define MBDBG(fmt, arg...) do { } while (0) -#endif - #define MB_FCR32(bay, r) ((bay)->base + ((r) >> 2)) #define MB_FCR8(bay, r) (((volatile u8 __iomem *)((bay)->base)) + (r)) @@ -76,28 +67,14 @@ struct media_bay_info { int index; int cached_gpio; int sleeping; + int user_lock; struct mutex lock; -#ifdef CONFIG_BLK_DEV_IDE_PMAC - ide_hwif_t *cd_port; - void __iomem *cd_base; - int cd_irq; - int cd_retry; -#endif -#if defined(CONFIG_BLK_DEV_IDE_PMAC) - int cd_index; -#endif }; #define MAX_BAYS 2 static struct media_bay_info media_bays[MAX_BAYS]; -int media_bay_count = 0; - -#ifdef CONFIG_BLK_DEV_IDE_PMAC -/* check the busy bit in the media-bay ide interface - (assumes the media-bay contains an ide device) */ -#define MB_IDE_READY(i) ((readb(media_bays[i].cd_base + 0x70) & 0x80) == 0) -#endif +static int media_bay_count = 0; /* * Wait that number of ms between each step in normal polling mode @@ -130,20 +107,10 @@ int media_bay_count = 0; /* * Wait this many ticks after an IDE device (e.g. CD-ROM) is inserted - * (or until the device is ready) before waiting for busy bit to disappear + * (or until the device is ready) before calling into the driver */ #define MB_IDE_WAIT 1000 -/* - * Timeout waiting for busy bit of an IDE device to go down - */ -#define MB_IDE_TIMEOUT 5000 - -/* - * Max retries of the full power up/down sequence for an IDE device - */ -#define MAX_CD_RETRIES 3 - /* * States of a media bay */ @@ -153,7 +120,6 @@ enum { mb_enabling_bay, /* enable bits set, waiting MB_RESET_DELAY */ mb_resetting, /* reset bit unset, waiting MB_SETUP_DELAY */ mb_ide_resetting, /* IDE reset bit unser, waiting MB_IDE_WAIT */ - mb_ide_waiting, /* Waiting for BUSY bit to go away until MB_IDE_TIMEOUT */ mb_up, /* Media bay full */ mb_powering_down /* Powering down (avoid too fast down/up) */ }; @@ -373,12 +339,12 @@ static inline void set_mb_power(struct media_bay_info* bay, int onoff) if (onoff) { bay->ops->power(bay, 1); bay->state = mb_powering_up; - MBDBG("mediabay%d: powering up\n", bay->index); + pr_debug("mediabay%d: powering up\n", bay->index); } else { /* Make sure everything is powered down & disabled */ bay->ops->power(bay, 0); bay->state = mb_powering_down; - MBDBG("mediabay%d: powering down\n", bay->index); + pr_debug("mediabay%d: powering down\n", bay->index); } bay->timer = msecs_to_jiffies(MB_POWER_DELAY); } @@ -387,107 +353,118 @@ static void poll_media_bay(struct media_bay_info* bay) { int id = bay->ops->content(bay); - if (id == bay->last_value) { - if (id != bay->content_id) { - bay->value_count += msecs_to_jiffies(MB_POLL_DELAY); - if (bay->value_count >= msecs_to_jiffies(MB_STABLE_DELAY)) { - /* If the device type changes without going thru - * "MB_NO", we force a pass by "MB_NO" to make sure - * things are properly reset - */ - if ((id != MB_NO) && (bay->content_id != MB_NO)) { - id = MB_NO; - MBDBG("mediabay%d: forcing MB_NO\n", bay->index); - } - MBDBG("mediabay%d: switching to %d\n", bay->index, id); - set_mb_power(bay, id != MB_NO); - bay->content_id = id; - if (id == MB_NO) { -#ifdef CONFIG_BLK_DEV_IDE_PMAC - bay->cd_retry = 0; -#endif - printk(KERN_INFO "media bay %d is empty\n", bay->index); - } - } - } - } else { + static char *mb_content_types[] = { + "a floppy drive", + "a floppy drive", + "an unsuported audio device", + "an ATA device", + "an unsupported PCI device", + "an unknown device", + }; + + if (id != bay->last_value) { bay->last_value = id; bay->value_count = 0; + return; + } + if (id == bay->content_id) + return; + + bay->value_count += msecs_to_jiffies(MB_POLL_DELAY); + if (bay->value_count >= msecs_to_jiffies(MB_STABLE_DELAY)) { + /* If the device type changes without going thru + * "MB_NO", we force a pass by "MB_NO" to make sure + * things are properly reset + */ + if ((id != MB_NO) && (bay->content_id != MB_NO)) { + id = MB_NO; + pr_debug("mediabay%d: forcing MB_NO\n", bay->index); + } + pr_debug("mediabay%d: switching to %d\n", bay->index, id); + set_mb_power(bay, id != MB_NO); + bay->content_id = id; + if (id >= MB_NO || id < 0) + printk(KERN_INFO "mediabay%d: Bay is now empty\n", bay->index); + else + printk(KERN_INFO "mediabay%d: Bay contains %s\n", + bay->index, mb_content_types[id]); } } -#ifdef CONFIG_BLK_DEV_IDE_PMAC -int check_media_bay(struct device_node *which_bay, int what) +int check_media_bay(struct macio_dev *baydev) { - int i; + struct media_bay_info* bay; + int id; - for (i=0; iofdev.node) { - if ((what == media_bays[i].content_id) && media_bays[i].state == mb_up) - return 0; - media_bays[i].cd_index = -1; - return -EINVAL; - } - return -ENODEV; + if (baydev == NULL) + return MB_NO; + + /* This returns an instant snapshot, not locking, sine + * we may be called with the bay lock held. The resulting + * fuzzyness of the result if called at the wrong time is + * not actually a huge deal + */ + bay = macio_get_drvdata(baydev); + if (bay == NULL) + return MB_NO; + id = bay->content_id; + if (bay->state != mb_up) + return MB_NO; + if (id == MB_FD1) + return MB_FD; + return id; } -EXPORT_SYMBOL(check_media_bay); +EXPORT_SYMBOL_GPL(check_media_bay); -int check_media_bay_by_base(unsigned long base, int what) +void lock_media_bay(struct macio_dev *baydev) { - int i; - - for (i=0; ilock); + bay->user_lock = 1; } -EXPORT_SYMBOL_GPL(check_media_bay_by_base); +EXPORT_SYMBOL_GPL(lock_media_bay); -int media_bay_set_ide_infos(struct device_node* which_bay, unsigned long base, - int irq, ide_hwif_t *hwif) +void unlock_media_bay(struct macio_dev *baydev) { - int i; + struct media_bay_info* bay; - for (i=0; imdev && which_bay == bay->mdev->ofdev.node) { - int timeout = 5000, index = hwif->index; - - mutex_lock(&bay->lock); - - bay->cd_port = hwif; - bay->cd_base = (void __iomem *) base; - bay->cd_irq = irq; - - if ((MB_CD != bay->content_id) || bay->state != mb_up) { - mutex_unlock(&bay->lock); - return 0; - } - printk(KERN_DEBUG "Registered ide%d for media bay %d\n", index, i); - do { - if (MB_IDE_READY(i)) { - bay->cd_index = index; - mutex_unlock(&bay->lock); - return 0; - } - mdelay(1); - } while(--timeout); - printk(KERN_DEBUG "Timeount waiting IDE in bay %d\n", i); - mutex_unlock(&bay->lock); - return -ENODEV; - } + if (baydev == NULL) + return; + bay = macio_get_drvdata(baydev); + if (bay == NULL) + return; + if (bay->user_lock) { + bay->user_lock = 0; + mutex_unlock(&bay->lock); } +} +EXPORT_SYMBOL_GPL(unlock_media_bay); - return -ENODEV; +static int mb_broadcast_hotplug(struct device *dev, void *data) +{ + struct media_bay_info* bay = data; + struct macio_dev *mdev; + struct macio_driver *drv; + int state; + + if (dev->bus != &macio_bus_type) + return 0; + + state = bay->state == mb_up ? bay->content_id : MB_NO; + if (state == MB_FD1) + state = MB_FD; + mdev = to_macio_device(dev); + drv = to_macio_driver(dev->driver); + if (dev->driver && drv->mediabay_event) + drv->mediabay_event(mdev, state); + return 0; } -EXPORT_SYMBOL_GPL(media_bay_set_ide_infos); -#endif /* CONFIG_BLK_DEV_IDE_PMAC */ static void media_bay_step(int i) { @@ -497,8 +474,8 @@ static void media_bay_step(int i) if (bay->state != mb_powering_down) poll_media_bay(bay); - /* If timer expired or polling IDE busy, run state machine */ - if ((bay->state != mb_ide_waiting) && (bay->timer != 0)) { + /* If timer expired run state machine */ + if (bay->timer != 0) { bay->timer -= msecs_to_jiffies(MB_POLL_DELAY); if (bay->timer > 0) return; @@ -508,100 +485,50 @@ static void media_bay_step(int i) switch(bay->state) { case mb_powering_up: if (bay->ops->setup_bus(bay, bay->last_value) < 0) { - MBDBG("mediabay%d: device not supported (kind:%d)\n", i, bay->content_id); + pr_debug("mediabay%d: device not supported (kind:%d)\n", + i, bay->content_id); set_mb_power(bay, 0); break; } bay->timer = msecs_to_jiffies(MB_RESET_DELAY); bay->state = mb_enabling_bay; - MBDBG("mediabay%d: enabling (kind:%d)\n", i, bay->content_id); + pr_debug("mediabay%d: enabling (kind:%d)\n", i, bay->content_id); break; case mb_enabling_bay: bay->ops->un_reset(bay); bay->timer = msecs_to_jiffies(MB_SETUP_DELAY); bay->state = mb_resetting; - MBDBG("mediabay%d: waiting reset (kind:%d)\n", i, bay->content_id); + pr_debug("mediabay%d: releasing bay reset (kind:%d)\n", + i, bay->content_id); break; case mb_resetting: if (bay->content_id != MB_CD) { - MBDBG("mediabay%d: bay is up (kind:%d)\n", i, bay->content_id); + pr_debug("mediabay%d: bay is up (kind:%d)\n", i, + bay->content_id); bay->state = mb_up; + device_for_each_child(&bay->mdev->ofdev.dev, + bay, mb_broadcast_hotplug); break; } -#ifdef CONFIG_BLK_DEV_IDE_PMAC - MBDBG("mediabay%d: waiting IDE reset (kind:%d)\n", i, bay->content_id); + pr_debug("mediabay%d: releasing ATA reset (kind:%d)\n", + i, bay->content_id); bay->ops->un_reset_ide(bay); bay->timer = msecs_to_jiffies(MB_IDE_WAIT); bay->state = mb_ide_resetting; -#else - printk(KERN_DEBUG "media-bay %d is ide (not compiled in kernel)\n", i); - set_mb_power(bay, 0); -#endif /* CONFIG_BLK_DEV_IDE_PMAC */ break; -#ifdef CONFIG_BLK_DEV_IDE_PMAC + case mb_ide_resetting: - bay->timer = msecs_to_jiffies(MB_IDE_TIMEOUT); - bay->state = mb_ide_waiting; - MBDBG("mediabay%d: waiting IDE ready (kind:%d)\n", i, bay->content_id); + pr_debug("mediabay%d: bay is up (kind:%d)\n", i, bay->content_id); + bay->state = mb_up; + device_for_each_child(&bay->mdev->ofdev.dev, + bay, mb_broadcast_hotplug); break; - case mb_ide_waiting: - if (bay->cd_base == NULL) { - bay->timer = 0; - bay->state = mb_up; - MBDBG("mediabay%d: up before IDE init\n", i); - break; - } else if (MB_IDE_READY(i)) { - bay->timer = 0; - bay->state = mb_up; - if (bay->cd_index < 0) { - printk("mediabay %d, registering IDE...\n", i); - pmu_suspend(); - ide_port_scan(bay->cd_port); - if (bay->cd_port->present) - bay->cd_index = bay->cd_port->index; - pmu_resume(); - } - if (bay->cd_index == -1) { - /* We eventually do a retry */ - bay->cd_retry++; - printk("IDE register error\n"); - set_mb_power(bay, 0); - } else { - printk(KERN_DEBUG "media-bay %d is ide%d\n", i, bay->cd_index); - MBDBG("mediabay %d IDE ready\n", i); - } - break; - } else if (bay->timer > 0) - bay->timer -= msecs_to_jiffies(MB_POLL_DELAY); - if (bay->timer <= 0) { - printk("\nIDE Timeout in bay %d !, IDE state is: 0x%02x\n", - i, readb(bay->cd_base + 0x70)); - MBDBG("mediabay%d: nIDE Timeout !\n", i); - set_mb_power(bay, 0); - bay->timer = 0; - } - break; -#endif /* CONFIG_BLK_DEV_IDE_PMAC */ + case mb_powering_down: bay->state = mb_empty; -#ifdef CONFIG_BLK_DEV_IDE_PMAC - if (bay->cd_index >= 0) { - printk(KERN_DEBUG "Unregistering mb %d ide, index:%d\n", i, - bay->cd_index); - ide_port_unregister_devices(bay->cd_port); - bay->cd_index = -1; - } - if (bay->cd_retry) { - if (bay->cd_retry > MAX_CD_RETRIES) { - /* Should add an error sound (sort of beep in dmasound) */ - printk("\nmedia-bay %d, IDE device badly inserted or unrecognised\n", i); - } else { - /* Force a new power down/up sequence */ - bay->content_id = MB_NO; - } - } -#endif /* CONFIG_BLK_DEV_IDE_PMAC */ - MBDBG("mediabay%d: end of power down\n", i); + device_for_each_child(&bay->mdev->ofdev.dev, + bay, mb_broadcast_hotplug); + pr_debug("mediabay%d: end of power down\n", i); break; } } @@ -676,11 +603,6 @@ static int __devinit media_bay_attach(struct macio_dev *mdev, const struct of_de bay->last_value = bay->ops->content(bay); bay->value_count = msecs_to_jiffies(MB_STABLE_DELAY); bay->state = mb_empty; - do { - msleep(MB_POLL_DELAY); - media_bay_step(i); - } while((bay->state != mb_empty) && - (bay->state != mb_up)); /* Mark us ready by filling our mdev data */ macio_set_drvdata(mdev, bay); @@ -725,7 +647,7 @@ static int media_bay_resume(struct macio_dev *mdev) set_mb_power(bay, 0); msleep(MB_POWER_DELAY); if (bay->ops->content(bay) != bay->content_id) { - printk("mediabay%d: content changed during sleep...\n", bay->index); + printk("mediabay%d: Content changed during sleep...\n", bay->index); mutex_unlock(&bay->lock); return 0; } @@ -733,9 +655,6 @@ static int media_bay_resume(struct macio_dev *mdev) bay->last_value = bay->content_id; bay->value_count = msecs_to_jiffies(MB_STABLE_DELAY); bay->timer = msecs_to_jiffies(MB_POWER_DELAY); -#ifdef CONFIG_BLK_DEV_IDE_PMAC - bay->cd_retry = 0; -#endif do { msleep(MB_POLL_DELAY); media_bay_step(bay->index); @@ -823,9 +742,6 @@ static int __init media_bay_init(void) for (i=0; i Date: Thu, 3 Dec 2009 16:19:59 +0000 Subject: powerpc/therm_adt746x: Record pwm invert bit at module load time] In commit 0512a9a8e277a9de2820211eef964473b714ae65, we unilaterally zero the "pwm invert" bit in the fan behavior configuration register. On my PowerBook G4, this results in the fans going to full speed at low temperature and shutting off at high temperature because the pwm invert bit is supposed to be set. Therefore, record the pwm invert bit at driver load time, and write the bit into the fan behavior control register. This restores correct behavior on my PBG4 and should work around the bit being set to the wrong value after suspend/resume (which is what the original patch was trying to fix). It also fixes a minor omission where the pwm invert bit correction is NOT performed when switching into automatic mode. Signed-off-by: Darrick J. Wong CC: Signed-off-by: Benjamin Herrenschmidt --- drivers/macintosh/therm_adt746x.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/macintosh') diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c index 95b676a19be7..5ff47ba7f2d0 100644 --- a/drivers/macintosh/therm_adt746x.c +++ b/drivers/macintosh/therm_adt746x.c @@ -79,6 +79,7 @@ struct thermostat { u8 limits[3]; int last_speed[2]; int last_var[2]; + int pwm_inv[2]; }; static enum {ADT7460, ADT7467} therm_type; @@ -229,19 +230,23 @@ static void write_fan_speed(struct thermostat *th, int speed, int fan) if (speed >= 0) { manual = read_reg(th, MANUAL_MODE[fan]); + manual &= ~INVERT_MASK; write_reg(th, MANUAL_MODE[fan], - (manual|MANUAL_MASK) & (~INVERT_MASK)); + manual | MANUAL_MASK | th->pwm_inv[fan]); write_reg(th, FAN_SPD_SET[fan], speed); } else { /* back to automatic */ if(therm_type == ADT7460) { manual = read_reg(th, MANUAL_MODE[fan]) & (~MANUAL_MASK); - + manual &= ~INVERT_MASK; + manual |= th->pwm_inv[fan]; write_reg(th, MANUAL_MODE[fan], manual|REM_CONTROL[fan]); } else { manual = read_reg(th, MANUAL_MODE[fan]); + manual &= ~INVERT_MASK; + manual |= th->pwm_inv[fan]; write_reg(th, MANUAL_MODE[fan], manual&(~AUTO_MASK)); } } @@ -418,6 +423,10 @@ static int probe_thermostat(struct i2c_client *client, thermostat = th; + /* record invert bit status because fw can corrupt it after suspend */ + th->pwm_inv[0] = read_reg(th, MANUAL_MODE[0]) & INVERT_MASK; + th->pwm_inv[1] = read_reg(th, MANUAL_MODE[1]) & INVERT_MASK; + /* be sure to really write fan speed the first time */ th->last_speed[0] = -2; th->last_speed[1] = -2; -- cgit v1.2.3-59-g8ed1b