Path: blob/master/arch/powerpc/platforms/powermac/pfunc_base.c
10818 views
#include <linux/types.h>1#include <linux/init.h>2#include <linux/delay.h>3#include <linux/kernel.h>4#include <linux/interrupt.h>5#include <linux/spinlock.h>67#include <asm/pmac_feature.h>8#include <asm/pmac_pfunc.h>910#undef DEBUG11#ifdef DEBUG12#define DBG(fmt...) printk(fmt)13#else14#define DBG(fmt...)15#endif1617static irqreturn_t macio_gpio_irq(int irq, void *data)18{19pmf_do_irq(data);2021return IRQ_HANDLED;22}2324static int macio_do_gpio_irq_enable(struct pmf_function *func)25{26unsigned int irq = irq_of_parse_and_map(func->node, 0);27if (irq == NO_IRQ)28return -EINVAL;29return request_irq(irq, macio_gpio_irq, 0, func->node->name, func);30}3132static int macio_do_gpio_irq_disable(struct pmf_function *func)33{34unsigned int irq = irq_of_parse_and_map(func->node, 0);35if (irq == NO_IRQ)36return -EINVAL;37free_irq(irq, func);38return 0;39}4041static int macio_do_gpio_write(PMF_STD_ARGS, u8 value, u8 mask)42{43u8 __iomem *addr = (u8 __iomem *)func->driver_data;44unsigned long flags;45u8 tmp;4647/* Check polarity */48if (args && args->count && !args->u[0].v)49value = ~value;5051/* Toggle the GPIO */52raw_spin_lock_irqsave(&feature_lock, flags);53tmp = readb(addr);54tmp = (tmp & ~mask) | (value & mask);55DBG("Do write 0x%02x to GPIO %s (%p)\n",56tmp, func->node->full_name, addr);57writeb(tmp, addr);58raw_spin_unlock_irqrestore(&feature_lock, flags);5960return 0;61}6263static int macio_do_gpio_read(PMF_STD_ARGS, u8 mask, int rshift, u8 xor)64{65u8 __iomem *addr = (u8 __iomem *)func->driver_data;66u32 value;6768/* Check if we have room for reply */69if (args == NULL || args->count == 0 || args->u[0].p == NULL)70return -EINVAL;7172value = readb(addr);73*args->u[0].p = ((value & mask) >> rshift) ^ xor;7475return 0;76}7778static int macio_do_delay(PMF_STD_ARGS, u32 duration)79{80/* assume we can sleep ! */81msleep((duration + 999) / 1000);82return 0;83}8485static struct pmf_handlers macio_gpio_handlers = {86.irq_enable = macio_do_gpio_irq_enable,87.irq_disable = macio_do_gpio_irq_disable,88.write_gpio = macio_do_gpio_write,89.read_gpio = macio_do_gpio_read,90.delay = macio_do_delay,91};9293static void macio_gpio_init_one(struct macio_chip *macio)94{95struct device_node *gparent, *gp;9697/*98* Find the "gpio" parent node99*/100101for (gparent = NULL;102(gparent = of_get_next_child(macio->of_node, gparent)) != NULL;)103if (strcmp(gparent->name, "gpio") == 0)104break;105if (gparent == NULL)106return;107108DBG("Installing GPIO functions for macio %s\n",109macio->of_node->full_name);110111/*112* Ok, got one, we dont need anything special to track them down, so113* we just create them all114*/115for (gp = NULL; (gp = of_get_next_child(gparent, gp)) != NULL;) {116const u32 *reg = of_get_property(gp, "reg", NULL);117unsigned long offset;118if (reg == NULL)119continue;120offset = *reg;121/* Deal with old style device-tree. We can safely hard code the122* offset for now too even if it's a bit gross ...123*/124if (offset < 0x50)125offset += 0x50;126offset += (unsigned long)macio->base;127pmf_register_driver(gp, &macio_gpio_handlers, (void *)offset);128}129130DBG("Calling initial GPIO functions for macio %s\n",131macio->of_node->full_name);132133/* And now we run all the init ones */134for (gp = NULL; (gp = of_get_next_child(gparent, gp)) != NULL;)135pmf_do_functions(gp, NULL, 0, PMF_FLAGS_ON_INIT, NULL);136137/* Note: We do not at this point implement the "at sleep" or "at wake"138* functions. I yet to find any for GPIOs anyway139*/140}141142static int macio_do_write_reg32(PMF_STD_ARGS, u32 offset, u32 value, u32 mask)143{144struct macio_chip *macio = func->driver_data;145unsigned long flags;146147raw_spin_lock_irqsave(&feature_lock, flags);148MACIO_OUT32(offset, (MACIO_IN32(offset) & ~mask) | (value & mask));149raw_spin_unlock_irqrestore(&feature_lock, flags);150return 0;151}152153static int macio_do_read_reg32(PMF_STD_ARGS, u32 offset)154{155struct macio_chip *macio = func->driver_data;156157/* Check if we have room for reply */158if (args == NULL || args->count == 0 || args->u[0].p == NULL)159return -EINVAL;160161*args->u[0].p = MACIO_IN32(offset);162return 0;163}164165static int macio_do_write_reg8(PMF_STD_ARGS, u32 offset, u8 value, u8 mask)166{167struct macio_chip *macio = func->driver_data;168unsigned long flags;169170raw_spin_lock_irqsave(&feature_lock, flags);171MACIO_OUT8(offset, (MACIO_IN8(offset) & ~mask) | (value & mask));172raw_spin_unlock_irqrestore(&feature_lock, flags);173return 0;174}175176static int macio_do_read_reg8(PMF_STD_ARGS, u32 offset)177{178struct macio_chip *macio = func->driver_data;179180/* Check if we have room for reply */181if (args == NULL || args->count == 0 || args->u[0].p == NULL)182return -EINVAL;183184*((u8 *)(args->u[0].p)) = MACIO_IN8(offset);185return 0;186}187188static int macio_do_read_reg32_msrx(PMF_STD_ARGS, u32 offset, u32 mask,189u32 shift, u32 xor)190{191struct macio_chip *macio = func->driver_data;192193/* Check if we have room for reply */194if (args == NULL || args->count == 0 || args->u[0].p == NULL)195return -EINVAL;196197*args->u[0].p = ((MACIO_IN32(offset) & mask) >> shift) ^ xor;198return 0;199}200201static int macio_do_read_reg8_msrx(PMF_STD_ARGS, u32 offset, u32 mask,202u32 shift, u32 xor)203{204struct macio_chip *macio = func->driver_data;205206/* Check if we have room for reply */207if (args == NULL || args->count == 0 || args->u[0].p == NULL)208return -EINVAL;209210*((u8 *)(args->u[0].p)) = ((MACIO_IN8(offset) & mask) >> shift) ^ xor;211return 0;212}213214static int macio_do_write_reg32_slm(PMF_STD_ARGS, u32 offset, u32 shift,215u32 mask)216{217struct macio_chip *macio = func->driver_data;218unsigned long flags;219u32 tmp, val;220221/* Check args */222if (args == NULL || args->count == 0)223return -EINVAL;224225raw_spin_lock_irqsave(&feature_lock, flags);226tmp = MACIO_IN32(offset);227val = args->u[0].v << shift;228tmp = (tmp & ~mask) | (val & mask);229MACIO_OUT32(offset, tmp);230raw_spin_unlock_irqrestore(&feature_lock, flags);231return 0;232}233234static int macio_do_write_reg8_slm(PMF_STD_ARGS, u32 offset, u32 shift,235u32 mask)236{237struct macio_chip *macio = func->driver_data;238unsigned long flags;239u32 tmp, val;240241/* Check args */242if (args == NULL || args->count == 0)243return -EINVAL;244245raw_spin_lock_irqsave(&feature_lock, flags);246tmp = MACIO_IN8(offset);247val = args->u[0].v << shift;248tmp = (tmp & ~mask) | (val & mask);249MACIO_OUT8(offset, tmp);250raw_spin_unlock_irqrestore(&feature_lock, flags);251return 0;252}253254static struct pmf_handlers macio_mmio_handlers = {255.write_reg32 = macio_do_write_reg32,256.read_reg32 = macio_do_read_reg32,257.write_reg8 = macio_do_write_reg8,258.read_reg8 = macio_do_read_reg8,259.read_reg32_msrx = macio_do_read_reg32_msrx,260.read_reg8_msrx = macio_do_read_reg8_msrx,261.write_reg32_slm = macio_do_write_reg32_slm,262.write_reg8_slm = macio_do_write_reg8_slm,263.delay = macio_do_delay,264};265266static void macio_mmio_init_one(struct macio_chip *macio)267{268DBG("Installing MMIO functions for macio %s\n",269macio->of_node->full_name);270271pmf_register_driver(macio->of_node, &macio_mmio_handlers, macio);272}273274static struct device_node *unin_hwclock;275276static int unin_do_write_reg32(PMF_STD_ARGS, u32 offset, u32 value, u32 mask)277{278unsigned long flags;279280raw_spin_lock_irqsave(&feature_lock, flags);281/* This is fairly bogus in darwin, but it should work for our needs282* implemeted that way:283*/284UN_OUT(offset, (UN_IN(offset) & ~mask) | (value & mask));285raw_spin_unlock_irqrestore(&feature_lock, flags);286return 0;287}288289290static struct pmf_handlers unin_mmio_handlers = {291.write_reg32 = unin_do_write_reg32,292.delay = macio_do_delay,293};294295static void uninorth_install_pfunc(void)296{297struct device_node *np;298299DBG("Installing functions for UniN %s\n",300uninorth_node->full_name);301302/*303* Install handlers for the bridge itself304*/305pmf_register_driver(uninorth_node, &unin_mmio_handlers, NULL);306pmf_do_functions(uninorth_node, NULL, 0, PMF_FLAGS_ON_INIT, NULL);307308309/*310* Install handlers for the hwclock child if any311*/312for (np = NULL; (np = of_get_next_child(uninorth_node, np)) != NULL;)313if (strcmp(np->name, "hw-clock") == 0) {314unin_hwclock = np;315break;316}317if (unin_hwclock) {318DBG("Installing functions for UniN clock %s\n",319unin_hwclock->full_name);320pmf_register_driver(unin_hwclock, &unin_mmio_handlers, NULL);321pmf_do_functions(unin_hwclock, NULL, 0, PMF_FLAGS_ON_INIT,322NULL);323}324}325326/* We export this as the SMP code might init us early */327int __init pmac_pfunc_base_install(void)328{329static int pfbase_inited;330int i;331332if (pfbase_inited)333return 0;334pfbase_inited = 1;335336if (!machine_is(powermac))337return 0;338339DBG("Installing base platform functions...\n");340341/*342* Locate mac-io chips and install handlers343*/344for (i = 0 ; i < MAX_MACIO_CHIPS; i++) {345if (macio_chips[i].of_node) {346macio_mmio_init_one(&macio_chips[i]);347macio_gpio_init_one(&macio_chips[i]);348}349}350351/*352* Install handlers for northbridge and direct mapped hwclock353* if any. We do not implement the config space access callback354* which is only ever used for functions that we do not call in355* the current driver (enabling/disabling cells in U2, mostly used356* to restore the PCI settings, we do that differently)357*/358if (uninorth_node && uninorth_base)359uninorth_install_pfunc();360361DBG("All base functions installed\n");362363return 0;364}365machine_arch_initcall(powermac, pmac_pfunc_base_install);366367#ifdef CONFIG_PM368369/* Those can be called by pmac_feature. Ultimately, I should use a sysdev370* or a device, but for now, that's good enough until I sort out some371* ordering issues. Also, we do not bother with GPIOs, as so far I yet have372* to see a case where a GPIO function has the on-suspend or on-resume bit373*/374void pmac_pfunc_base_suspend(void)375{376int i;377378for (i = 0 ; i < MAX_MACIO_CHIPS; i++) {379if (macio_chips[i].of_node)380pmf_do_functions(macio_chips[i].of_node, NULL, 0,381PMF_FLAGS_ON_SLEEP, NULL);382}383if (uninorth_node)384pmf_do_functions(uninorth_node, NULL, 0,385PMF_FLAGS_ON_SLEEP, NULL);386if (unin_hwclock)387pmf_do_functions(unin_hwclock, NULL, 0,388PMF_FLAGS_ON_SLEEP, NULL);389}390391void pmac_pfunc_base_resume(void)392{393int i;394395if (unin_hwclock)396pmf_do_functions(unin_hwclock, NULL, 0,397PMF_FLAGS_ON_WAKE, NULL);398if (uninorth_node)399pmf_do_functions(uninorth_node, NULL, 0,400PMF_FLAGS_ON_WAKE, NULL);401for (i = 0 ; i < MAX_MACIO_CHIPS; i++) {402if (macio_chips[i].of_node)403pmf_do_functions(macio_chips[i].of_node, NULL, 0,404PMF_FLAGS_ON_WAKE, NULL);405}406}407408#endif /* CONFIG_PM */409410411