Path: blob/master/arch/powerpc/platforms/powermac/pfunc_base.c
26481 views
// SPDX-License-Identifier: GPL-2.01#include <linux/types.h>2#include <linux/init.h>3#include <linux/delay.h>4#include <linux/kernel.h>5#include <linux/interrupt.h>6#include <linux/spinlock.h>7#include <linux/of_irq.h>89#include <asm/pmac_feature.h>10#include <asm/pmac_pfunc.h>1112#undef DEBUG13#ifdef DEBUG14#define DBG(fmt...) printk(fmt)15#else16#define DBG(fmt...)17#endif1819static irqreturn_t macio_gpio_irq(int irq, void *data)20{21pmf_do_irq(data);2223return IRQ_HANDLED;24}2526static int macio_do_gpio_irq_enable(struct pmf_function *func)27{28unsigned int irq = irq_of_parse_and_map(func->node, 0);29if (!irq)30return -EINVAL;31return request_irq(irq, macio_gpio_irq, 0, func->node->name, func);32}3334static int macio_do_gpio_irq_disable(struct pmf_function *func)35{36unsigned int irq = irq_of_parse_and_map(func->node, 0);37if (!irq)38return -EINVAL;39free_irq(irq, func);40return 0;41}4243static int macio_do_gpio_write(PMF_STD_ARGS, u8 value, u8 mask)44{45u8 __iomem *addr = (u8 __iomem *)func->driver_data;46unsigned long flags;47u8 tmp;4849/* Check polarity */50if (args && args->count && !args->u[0].v)51value = ~value;5253/* Toggle the GPIO */54raw_spin_lock_irqsave(&feature_lock, flags);55tmp = readb(addr);56tmp = (tmp & ~mask) | (value & mask);57DBG("Do write 0x%02x to GPIO %pOF (%p)\n",58tmp, func->node, addr);59writeb(tmp, addr);60raw_spin_unlock_irqrestore(&feature_lock, flags);6162return 0;63}6465static int macio_do_gpio_read(PMF_STD_ARGS, u8 mask, int rshift, u8 xor)66{67u8 __iomem *addr = (u8 __iomem *)func->driver_data;68u32 value;6970/* Check if we have room for reply */71if (args == NULL || args->count == 0 || args->u[0].p == NULL)72return -EINVAL;7374value = readb(addr);75*args->u[0].p = ((value & mask) >> rshift) ^ xor;7677return 0;78}7980static int macio_do_delay(PMF_STD_ARGS, u32 duration)81{82/* assume we can sleep ! */83msleep((duration + 999) / 1000);84return 0;85}8687static struct pmf_handlers macio_gpio_handlers = {88.irq_enable = macio_do_gpio_irq_enable,89.irq_disable = macio_do_gpio_irq_disable,90.write_gpio = macio_do_gpio_write,91.read_gpio = macio_do_gpio_read,92.delay = macio_do_delay,93};9495static void __init macio_gpio_init_one(struct macio_chip *macio)96{97struct device_node *gparent, *gp;9899/*100* Find the "gpio" parent node101*/102103for_each_child_of_node(macio->of_node, gparent)104if (of_node_name_eq(gparent, "gpio"))105break;106if (gparent == NULL)107return;108109DBG("Installing GPIO functions for macio %pOF\n",110macio->of_node);111112/*113* Ok, got one, we dont need anything special to track them down, so114* we just create them all115*/116for_each_child_of_node(gparent, gp) {117const u32 *reg = of_get_property(gp, "reg", NULL);118unsigned long offset;119if (reg == NULL)120continue;121offset = *reg;122/* Deal with old style device-tree. We can safely hard code the123* offset for now too even if it's a bit gross ...124*/125if (offset < 0x50)126offset += 0x50;127offset += (unsigned long)macio->base;128pmf_register_driver(gp, &macio_gpio_handlers, (void *)offset);129}130131DBG("Calling initial GPIO functions for macio %pOF\n",132macio->of_node);133134/* And now we run all the init ones */135for_each_child_of_node(gparent, gp)136pmf_do_functions(gp, NULL, 0, PMF_FLAGS_ON_INIT, NULL);137138of_node_put(gparent);139140/* Note: We do not at this point implement the "at sleep" or "at wake"141* functions. I yet to find any for GPIOs anyway142*/143}144145static int macio_do_write_reg32(PMF_STD_ARGS, u32 offset, u32 value, u32 mask)146{147struct macio_chip *macio = func->driver_data;148unsigned long flags;149150raw_spin_lock_irqsave(&feature_lock, flags);151MACIO_OUT32(offset, (MACIO_IN32(offset) & ~mask) | (value & mask));152raw_spin_unlock_irqrestore(&feature_lock, flags);153return 0;154}155156static int macio_do_read_reg32(PMF_STD_ARGS, u32 offset)157{158struct macio_chip *macio = func->driver_data;159160/* Check if we have room for reply */161if (args == NULL || args->count == 0 || args->u[0].p == NULL)162return -EINVAL;163164*args->u[0].p = MACIO_IN32(offset);165return 0;166}167168static int macio_do_write_reg8(PMF_STD_ARGS, u32 offset, u8 value, u8 mask)169{170struct macio_chip *macio = func->driver_data;171unsigned long flags;172173raw_spin_lock_irqsave(&feature_lock, flags);174MACIO_OUT8(offset, (MACIO_IN8(offset) & ~mask) | (value & mask));175raw_spin_unlock_irqrestore(&feature_lock, flags);176return 0;177}178179static int macio_do_read_reg8(PMF_STD_ARGS, u32 offset)180{181struct macio_chip *macio = func->driver_data;182183/* Check if we have room for reply */184if (args == NULL || args->count == 0 || args->u[0].p == NULL)185return -EINVAL;186187*((u8 *)(args->u[0].p)) = MACIO_IN8(offset);188return 0;189}190191static int macio_do_read_reg32_msrx(PMF_STD_ARGS, u32 offset, u32 mask,192u32 shift, u32 xor)193{194struct macio_chip *macio = func->driver_data;195196/* Check if we have room for reply */197if (args == NULL || args->count == 0 || args->u[0].p == NULL)198return -EINVAL;199200*args->u[0].p = ((MACIO_IN32(offset) & mask) >> shift) ^ xor;201return 0;202}203204static int macio_do_read_reg8_msrx(PMF_STD_ARGS, u32 offset, u32 mask,205u32 shift, u32 xor)206{207struct macio_chip *macio = func->driver_data;208209/* Check if we have room for reply */210if (args == NULL || args->count == 0 || args->u[0].p == NULL)211return -EINVAL;212213*((u8 *)(args->u[0].p)) = ((MACIO_IN8(offset) & mask) >> shift) ^ xor;214return 0;215}216217static int macio_do_write_reg32_slm(PMF_STD_ARGS, u32 offset, u32 shift,218u32 mask)219{220struct macio_chip *macio = func->driver_data;221unsigned long flags;222u32 tmp, val;223224/* Check args */225if (args == NULL || args->count == 0)226return -EINVAL;227228raw_spin_lock_irqsave(&feature_lock, flags);229tmp = MACIO_IN32(offset);230val = args->u[0].v << shift;231tmp = (tmp & ~mask) | (val & mask);232MACIO_OUT32(offset, tmp);233raw_spin_unlock_irqrestore(&feature_lock, flags);234return 0;235}236237static int macio_do_write_reg8_slm(PMF_STD_ARGS, u32 offset, u32 shift,238u32 mask)239{240struct macio_chip *macio = func->driver_data;241unsigned long flags;242u32 tmp, val;243244/* Check args */245if (args == NULL || args->count == 0)246return -EINVAL;247248raw_spin_lock_irqsave(&feature_lock, flags);249tmp = MACIO_IN8(offset);250val = args->u[0].v << shift;251tmp = (tmp & ~mask) | (val & mask);252MACIO_OUT8(offset, tmp);253raw_spin_unlock_irqrestore(&feature_lock, flags);254return 0;255}256257static struct pmf_handlers macio_mmio_handlers = {258.write_reg32 = macio_do_write_reg32,259.read_reg32 = macio_do_read_reg32,260.write_reg8 = macio_do_write_reg8,261.read_reg8 = macio_do_read_reg8,262.read_reg32_msrx = macio_do_read_reg32_msrx,263.read_reg8_msrx = macio_do_read_reg8_msrx,264.write_reg32_slm = macio_do_write_reg32_slm,265.write_reg8_slm = macio_do_write_reg8_slm,266.delay = macio_do_delay,267};268269static void __init macio_mmio_init_one(struct macio_chip *macio)270{271DBG("Installing MMIO functions for macio %pOF\n",272macio->of_node);273274pmf_register_driver(macio->of_node, &macio_mmio_handlers, macio);275}276277static struct device_node *unin_hwclock;278279static int unin_do_write_reg32(PMF_STD_ARGS, u32 offset, u32 value, u32 mask)280{281unsigned long flags;282283raw_spin_lock_irqsave(&feature_lock, flags);284/* This is fairly bogus in darwin, but it should work for our needs285* implemeted that way:286*/287UN_OUT(offset, (UN_IN(offset) & ~mask) | (value & mask));288raw_spin_unlock_irqrestore(&feature_lock, flags);289return 0;290}291292293static struct pmf_handlers unin_mmio_handlers = {294.write_reg32 = unin_do_write_reg32,295.delay = macio_do_delay,296};297298static void __init uninorth_install_pfunc(void)299{300struct device_node *np;301302DBG("Installing functions for UniN %pOF\n",303uninorth_node);304305/*306* Install handlers for the bridge itself307*/308pmf_register_driver(uninorth_node, &unin_mmio_handlers, NULL);309pmf_do_functions(uninorth_node, NULL, 0, PMF_FLAGS_ON_INIT, NULL);310311312/*313* Install handlers for the hwclock child if any314*/315for_each_child_of_node(uninorth_node, np)316if (of_node_name_eq(np, "hw-clock")) {317unin_hwclock = np;318break;319}320if (unin_hwclock) {321DBG("Installing functions for UniN clock %pOF\n",322unin_hwclock);323pmf_register_driver(unin_hwclock, &unin_mmio_handlers, NULL);324pmf_do_functions(unin_hwclock, NULL, 0, PMF_FLAGS_ON_INIT,325NULL);326}327}328329/* We export this as the SMP code might init us early */330int __init pmac_pfunc_base_install(void)331{332static int pfbase_inited;333int i;334335if (pfbase_inited)336return 0;337pfbase_inited = 1;338339if (!machine_is(powermac))340return 0;341342DBG("Installing base platform functions...\n");343344/*345* Locate mac-io chips and install handlers346*/347for (i = 0 ; i < MAX_MACIO_CHIPS; i++) {348if (macio_chips[i].of_node) {349macio_mmio_init_one(&macio_chips[i]);350macio_gpio_init_one(&macio_chips[i]);351}352}353354/*355* Install handlers for northbridge and direct mapped hwclock356* if any. We do not implement the config space access callback357* which is only ever used for functions that we do not call in358* the current driver (enabling/disabling cells in U2, mostly used359* to restore the PCI settings, we do that differently)360*/361if (uninorth_node && uninorth_base)362uninorth_install_pfunc();363364DBG("All base functions installed\n");365366return 0;367}368machine_arch_initcall(powermac, pmac_pfunc_base_install);369370#ifdef CONFIG_PM371372/* Those can be called by pmac_feature. Ultimately, I should use a sysdev373* or a device, but for now, that's good enough until I sort out some374* ordering issues. Also, we do not bother with GPIOs, as so far I yet have375* to see a case where a GPIO function has the on-suspend or on-resume bit376*/377void pmac_pfunc_base_suspend(void)378{379int i;380381for (i = 0 ; i < MAX_MACIO_CHIPS; i++) {382if (macio_chips[i].of_node)383pmf_do_functions(macio_chips[i].of_node, NULL, 0,384PMF_FLAGS_ON_SLEEP, NULL);385}386if (uninorth_node)387pmf_do_functions(uninorth_node, NULL, 0,388PMF_FLAGS_ON_SLEEP, NULL);389if (unin_hwclock)390pmf_do_functions(unin_hwclock, NULL, 0,391PMF_FLAGS_ON_SLEEP, NULL);392}393394void pmac_pfunc_base_resume(void)395{396int i;397398if (unin_hwclock)399pmf_do_functions(unin_hwclock, NULL, 0,400PMF_FLAGS_ON_WAKE, NULL);401if (uninorth_node)402pmf_do_functions(uninorth_node, NULL, 0,403PMF_FLAGS_ON_WAKE, NULL);404for (i = 0 ; i < MAX_MACIO_CHIPS; i++) {405if (macio_chips[i].of_node)406pmf_do_functions(macio_chips[i].of_node, NULL, 0,407PMF_FLAGS_ON_WAKE, NULL);408}409}410411#endif /* CONFIG_PM */412413414