162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci#include <linux/types.h> 362306a36Sopenharmony_ci#include <linux/init.h> 462306a36Sopenharmony_ci#include <linux/delay.h> 562306a36Sopenharmony_ci#include <linux/kernel.h> 662306a36Sopenharmony_ci#include <linux/interrupt.h> 762306a36Sopenharmony_ci#include <linux/spinlock.h> 862306a36Sopenharmony_ci#include <linux/of_irq.h> 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <asm/pmac_feature.h> 1162306a36Sopenharmony_ci#include <asm/pmac_pfunc.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#undef DEBUG 1462306a36Sopenharmony_ci#ifdef DEBUG 1562306a36Sopenharmony_ci#define DBG(fmt...) printk(fmt) 1662306a36Sopenharmony_ci#else 1762306a36Sopenharmony_ci#define DBG(fmt...) 1862306a36Sopenharmony_ci#endif 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_cistatic irqreturn_t macio_gpio_irq(int irq, void *data) 2162306a36Sopenharmony_ci{ 2262306a36Sopenharmony_ci pmf_do_irq(data); 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci return IRQ_HANDLED; 2562306a36Sopenharmony_ci} 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistatic int macio_do_gpio_irq_enable(struct pmf_function *func) 2862306a36Sopenharmony_ci{ 2962306a36Sopenharmony_ci unsigned int irq = irq_of_parse_and_map(func->node, 0); 3062306a36Sopenharmony_ci if (!irq) 3162306a36Sopenharmony_ci return -EINVAL; 3262306a36Sopenharmony_ci return request_irq(irq, macio_gpio_irq, 0, func->node->name, func); 3362306a36Sopenharmony_ci} 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_cistatic int macio_do_gpio_irq_disable(struct pmf_function *func) 3662306a36Sopenharmony_ci{ 3762306a36Sopenharmony_ci unsigned int irq = irq_of_parse_and_map(func->node, 0); 3862306a36Sopenharmony_ci if (!irq) 3962306a36Sopenharmony_ci return -EINVAL; 4062306a36Sopenharmony_ci free_irq(irq, func); 4162306a36Sopenharmony_ci return 0; 4262306a36Sopenharmony_ci} 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_cistatic int macio_do_gpio_write(PMF_STD_ARGS, u8 value, u8 mask) 4562306a36Sopenharmony_ci{ 4662306a36Sopenharmony_ci u8 __iomem *addr = (u8 __iomem *)func->driver_data; 4762306a36Sopenharmony_ci unsigned long flags; 4862306a36Sopenharmony_ci u8 tmp; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci /* Check polarity */ 5162306a36Sopenharmony_ci if (args && args->count && !args->u[0].v) 5262306a36Sopenharmony_ci value = ~value; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci /* Toggle the GPIO */ 5562306a36Sopenharmony_ci raw_spin_lock_irqsave(&feature_lock, flags); 5662306a36Sopenharmony_ci tmp = readb(addr); 5762306a36Sopenharmony_ci tmp = (tmp & ~mask) | (value & mask); 5862306a36Sopenharmony_ci DBG("Do write 0x%02x to GPIO %pOF (%p)\n", 5962306a36Sopenharmony_ci tmp, func->node, addr); 6062306a36Sopenharmony_ci writeb(tmp, addr); 6162306a36Sopenharmony_ci raw_spin_unlock_irqrestore(&feature_lock, flags); 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci return 0; 6462306a36Sopenharmony_ci} 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_cistatic int macio_do_gpio_read(PMF_STD_ARGS, u8 mask, int rshift, u8 xor) 6762306a36Sopenharmony_ci{ 6862306a36Sopenharmony_ci u8 __iomem *addr = (u8 __iomem *)func->driver_data; 6962306a36Sopenharmony_ci u32 value; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci /* Check if we have room for reply */ 7262306a36Sopenharmony_ci if (args == NULL || args->count == 0 || args->u[0].p == NULL) 7362306a36Sopenharmony_ci return -EINVAL; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci value = readb(addr); 7662306a36Sopenharmony_ci *args->u[0].p = ((value & mask) >> rshift) ^ xor; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci return 0; 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_cistatic int macio_do_delay(PMF_STD_ARGS, u32 duration) 8262306a36Sopenharmony_ci{ 8362306a36Sopenharmony_ci /* assume we can sleep ! */ 8462306a36Sopenharmony_ci msleep((duration + 999) / 1000); 8562306a36Sopenharmony_ci return 0; 8662306a36Sopenharmony_ci} 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_cistatic struct pmf_handlers macio_gpio_handlers = { 8962306a36Sopenharmony_ci .irq_enable = macio_do_gpio_irq_enable, 9062306a36Sopenharmony_ci .irq_disable = macio_do_gpio_irq_disable, 9162306a36Sopenharmony_ci .write_gpio = macio_do_gpio_write, 9262306a36Sopenharmony_ci .read_gpio = macio_do_gpio_read, 9362306a36Sopenharmony_ci .delay = macio_do_delay, 9462306a36Sopenharmony_ci}; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_cistatic void __init macio_gpio_init_one(struct macio_chip *macio) 9762306a36Sopenharmony_ci{ 9862306a36Sopenharmony_ci struct device_node *gparent, *gp; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci /* 10162306a36Sopenharmony_ci * Find the "gpio" parent node 10262306a36Sopenharmony_ci */ 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci for_each_child_of_node(macio->of_node, gparent) 10562306a36Sopenharmony_ci if (of_node_name_eq(gparent, "gpio")) 10662306a36Sopenharmony_ci break; 10762306a36Sopenharmony_ci if (gparent == NULL) 10862306a36Sopenharmony_ci return; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci DBG("Installing GPIO functions for macio %pOF\n", 11162306a36Sopenharmony_ci macio->of_node); 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci /* 11462306a36Sopenharmony_ci * Ok, got one, we dont need anything special to track them down, so 11562306a36Sopenharmony_ci * we just create them all 11662306a36Sopenharmony_ci */ 11762306a36Sopenharmony_ci for_each_child_of_node(gparent, gp) { 11862306a36Sopenharmony_ci const u32 *reg = of_get_property(gp, "reg", NULL); 11962306a36Sopenharmony_ci unsigned long offset; 12062306a36Sopenharmony_ci if (reg == NULL) 12162306a36Sopenharmony_ci continue; 12262306a36Sopenharmony_ci offset = *reg; 12362306a36Sopenharmony_ci /* Deal with old style device-tree. We can safely hard code the 12462306a36Sopenharmony_ci * offset for now too even if it's a bit gross ... 12562306a36Sopenharmony_ci */ 12662306a36Sopenharmony_ci if (offset < 0x50) 12762306a36Sopenharmony_ci offset += 0x50; 12862306a36Sopenharmony_ci offset += (unsigned long)macio->base; 12962306a36Sopenharmony_ci pmf_register_driver(gp, &macio_gpio_handlers, (void *)offset); 13062306a36Sopenharmony_ci } 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci DBG("Calling initial GPIO functions for macio %pOF\n", 13362306a36Sopenharmony_ci macio->of_node); 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci /* And now we run all the init ones */ 13662306a36Sopenharmony_ci for_each_child_of_node(gparent, gp) 13762306a36Sopenharmony_ci pmf_do_functions(gp, NULL, 0, PMF_FLAGS_ON_INIT, NULL); 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci of_node_put(gparent); 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci /* Note: We do not at this point implement the "at sleep" or "at wake" 14262306a36Sopenharmony_ci * functions. I yet to find any for GPIOs anyway 14362306a36Sopenharmony_ci */ 14462306a36Sopenharmony_ci} 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_cistatic int macio_do_write_reg32(PMF_STD_ARGS, u32 offset, u32 value, u32 mask) 14762306a36Sopenharmony_ci{ 14862306a36Sopenharmony_ci struct macio_chip *macio = func->driver_data; 14962306a36Sopenharmony_ci unsigned long flags; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci raw_spin_lock_irqsave(&feature_lock, flags); 15262306a36Sopenharmony_ci MACIO_OUT32(offset, (MACIO_IN32(offset) & ~mask) | (value & mask)); 15362306a36Sopenharmony_ci raw_spin_unlock_irqrestore(&feature_lock, flags); 15462306a36Sopenharmony_ci return 0; 15562306a36Sopenharmony_ci} 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_cistatic int macio_do_read_reg32(PMF_STD_ARGS, u32 offset) 15862306a36Sopenharmony_ci{ 15962306a36Sopenharmony_ci struct macio_chip *macio = func->driver_data; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci /* Check if we have room for reply */ 16262306a36Sopenharmony_ci if (args == NULL || args->count == 0 || args->u[0].p == NULL) 16362306a36Sopenharmony_ci return -EINVAL; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci *args->u[0].p = MACIO_IN32(offset); 16662306a36Sopenharmony_ci return 0; 16762306a36Sopenharmony_ci} 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_cistatic int macio_do_write_reg8(PMF_STD_ARGS, u32 offset, u8 value, u8 mask) 17062306a36Sopenharmony_ci{ 17162306a36Sopenharmony_ci struct macio_chip *macio = func->driver_data; 17262306a36Sopenharmony_ci unsigned long flags; 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci raw_spin_lock_irqsave(&feature_lock, flags); 17562306a36Sopenharmony_ci MACIO_OUT8(offset, (MACIO_IN8(offset) & ~mask) | (value & mask)); 17662306a36Sopenharmony_ci raw_spin_unlock_irqrestore(&feature_lock, flags); 17762306a36Sopenharmony_ci return 0; 17862306a36Sopenharmony_ci} 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_cistatic int macio_do_read_reg8(PMF_STD_ARGS, u32 offset) 18162306a36Sopenharmony_ci{ 18262306a36Sopenharmony_ci struct macio_chip *macio = func->driver_data; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci /* Check if we have room for reply */ 18562306a36Sopenharmony_ci if (args == NULL || args->count == 0 || args->u[0].p == NULL) 18662306a36Sopenharmony_ci return -EINVAL; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci *((u8 *)(args->u[0].p)) = MACIO_IN8(offset); 18962306a36Sopenharmony_ci return 0; 19062306a36Sopenharmony_ci} 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cistatic int macio_do_read_reg32_msrx(PMF_STD_ARGS, u32 offset, u32 mask, 19362306a36Sopenharmony_ci u32 shift, u32 xor) 19462306a36Sopenharmony_ci{ 19562306a36Sopenharmony_ci struct macio_chip *macio = func->driver_data; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci /* Check if we have room for reply */ 19862306a36Sopenharmony_ci if (args == NULL || args->count == 0 || args->u[0].p == NULL) 19962306a36Sopenharmony_ci return -EINVAL; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci *args->u[0].p = ((MACIO_IN32(offset) & mask) >> shift) ^ xor; 20262306a36Sopenharmony_ci return 0; 20362306a36Sopenharmony_ci} 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_cistatic int macio_do_read_reg8_msrx(PMF_STD_ARGS, u32 offset, u32 mask, 20662306a36Sopenharmony_ci u32 shift, u32 xor) 20762306a36Sopenharmony_ci{ 20862306a36Sopenharmony_ci struct macio_chip *macio = func->driver_data; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci /* Check if we have room for reply */ 21162306a36Sopenharmony_ci if (args == NULL || args->count == 0 || args->u[0].p == NULL) 21262306a36Sopenharmony_ci return -EINVAL; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci *((u8 *)(args->u[0].p)) = ((MACIO_IN8(offset) & mask) >> shift) ^ xor; 21562306a36Sopenharmony_ci return 0; 21662306a36Sopenharmony_ci} 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_cistatic int macio_do_write_reg32_slm(PMF_STD_ARGS, u32 offset, u32 shift, 21962306a36Sopenharmony_ci u32 mask) 22062306a36Sopenharmony_ci{ 22162306a36Sopenharmony_ci struct macio_chip *macio = func->driver_data; 22262306a36Sopenharmony_ci unsigned long flags; 22362306a36Sopenharmony_ci u32 tmp, val; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci /* Check args */ 22662306a36Sopenharmony_ci if (args == NULL || args->count == 0) 22762306a36Sopenharmony_ci return -EINVAL; 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci raw_spin_lock_irqsave(&feature_lock, flags); 23062306a36Sopenharmony_ci tmp = MACIO_IN32(offset); 23162306a36Sopenharmony_ci val = args->u[0].v << shift; 23262306a36Sopenharmony_ci tmp = (tmp & ~mask) | (val & mask); 23362306a36Sopenharmony_ci MACIO_OUT32(offset, tmp); 23462306a36Sopenharmony_ci raw_spin_unlock_irqrestore(&feature_lock, flags); 23562306a36Sopenharmony_ci return 0; 23662306a36Sopenharmony_ci} 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_cistatic int macio_do_write_reg8_slm(PMF_STD_ARGS, u32 offset, u32 shift, 23962306a36Sopenharmony_ci u32 mask) 24062306a36Sopenharmony_ci{ 24162306a36Sopenharmony_ci struct macio_chip *macio = func->driver_data; 24262306a36Sopenharmony_ci unsigned long flags; 24362306a36Sopenharmony_ci u32 tmp, val; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci /* Check args */ 24662306a36Sopenharmony_ci if (args == NULL || args->count == 0) 24762306a36Sopenharmony_ci return -EINVAL; 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci raw_spin_lock_irqsave(&feature_lock, flags); 25062306a36Sopenharmony_ci tmp = MACIO_IN8(offset); 25162306a36Sopenharmony_ci val = args->u[0].v << shift; 25262306a36Sopenharmony_ci tmp = (tmp & ~mask) | (val & mask); 25362306a36Sopenharmony_ci MACIO_OUT8(offset, tmp); 25462306a36Sopenharmony_ci raw_spin_unlock_irqrestore(&feature_lock, flags); 25562306a36Sopenharmony_ci return 0; 25662306a36Sopenharmony_ci} 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_cistatic struct pmf_handlers macio_mmio_handlers = { 25962306a36Sopenharmony_ci .write_reg32 = macio_do_write_reg32, 26062306a36Sopenharmony_ci .read_reg32 = macio_do_read_reg32, 26162306a36Sopenharmony_ci .write_reg8 = macio_do_write_reg8, 26262306a36Sopenharmony_ci .read_reg8 = macio_do_read_reg8, 26362306a36Sopenharmony_ci .read_reg32_msrx = macio_do_read_reg32_msrx, 26462306a36Sopenharmony_ci .read_reg8_msrx = macio_do_read_reg8_msrx, 26562306a36Sopenharmony_ci .write_reg32_slm = macio_do_write_reg32_slm, 26662306a36Sopenharmony_ci .write_reg8_slm = macio_do_write_reg8_slm, 26762306a36Sopenharmony_ci .delay = macio_do_delay, 26862306a36Sopenharmony_ci}; 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_cistatic void __init macio_mmio_init_one(struct macio_chip *macio) 27162306a36Sopenharmony_ci{ 27262306a36Sopenharmony_ci DBG("Installing MMIO functions for macio %pOF\n", 27362306a36Sopenharmony_ci macio->of_node); 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci pmf_register_driver(macio->of_node, &macio_mmio_handlers, macio); 27662306a36Sopenharmony_ci} 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_cistatic struct device_node *unin_hwclock; 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_cistatic int unin_do_write_reg32(PMF_STD_ARGS, u32 offset, u32 value, u32 mask) 28162306a36Sopenharmony_ci{ 28262306a36Sopenharmony_ci unsigned long flags; 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci raw_spin_lock_irqsave(&feature_lock, flags); 28562306a36Sopenharmony_ci /* This is fairly bogus in darwin, but it should work for our needs 28662306a36Sopenharmony_ci * implemeted that way: 28762306a36Sopenharmony_ci */ 28862306a36Sopenharmony_ci UN_OUT(offset, (UN_IN(offset) & ~mask) | (value & mask)); 28962306a36Sopenharmony_ci raw_spin_unlock_irqrestore(&feature_lock, flags); 29062306a36Sopenharmony_ci return 0; 29162306a36Sopenharmony_ci} 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_cistatic struct pmf_handlers unin_mmio_handlers = { 29562306a36Sopenharmony_ci .write_reg32 = unin_do_write_reg32, 29662306a36Sopenharmony_ci .delay = macio_do_delay, 29762306a36Sopenharmony_ci}; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_cistatic void __init uninorth_install_pfunc(void) 30062306a36Sopenharmony_ci{ 30162306a36Sopenharmony_ci struct device_node *np; 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci DBG("Installing functions for UniN %pOF\n", 30462306a36Sopenharmony_ci uninorth_node); 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci /* 30762306a36Sopenharmony_ci * Install handlers for the bridge itself 30862306a36Sopenharmony_ci */ 30962306a36Sopenharmony_ci pmf_register_driver(uninorth_node, &unin_mmio_handlers, NULL); 31062306a36Sopenharmony_ci pmf_do_functions(uninorth_node, NULL, 0, PMF_FLAGS_ON_INIT, NULL); 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci /* 31462306a36Sopenharmony_ci * Install handlers for the hwclock child if any 31562306a36Sopenharmony_ci */ 31662306a36Sopenharmony_ci for (np = NULL; (np = of_get_next_child(uninorth_node, np)) != NULL;) 31762306a36Sopenharmony_ci if (of_node_name_eq(np, "hw-clock")) { 31862306a36Sopenharmony_ci unin_hwclock = np; 31962306a36Sopenharmony_ci break; 32062306a36Sopenharmony_ci } 32162306a36Sopenharmony_ci if (unin_hwclock) { 32262306a36Sopenharmony_ci DBG("Installing functions for UniN clock %pOF\n", 32362306a36Sopenharmony_ci unin_hwclock); 32462306a36Sopenharmony_ci pmf_register_driver(unin_hwclock, &unin_mmio_handlers, NULL); 32562306a36Sopenharmony_ci pmf_do_functions(unin_hwclock, NULL, 0, PMF_FLAGS_ON_INIT, 32662306a36Sopenharmony_ci NULL); 32762306a36Sopenharmony_ci } 32862306a36Sopenharmony_ci} 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci/* We export this as the SMP code might init us early */ 33162306a36Sopenharmony_ciint __init pmac_pfunc_base_install(void) 33262306a36Sopenharmony_ci{ 33362306a36Sopenharmony_ci static int pfbase_inited; 33462306a36Sopenharmony_ci int i; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci if (pfbase_inited) 33762306a36Sopenharmony_ci return 0; 33862306a36Sopenharmony_ci pfbase_inited = 1; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci if (!machine_is(powermac)) 34162306a36Sopenharmony_ci return 0; 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci DBG("Installing base platform functions...\n"); 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci /* 34662306a36Sopenharmony_ci * Locate mac-io chips and install handlers 34762306a36Sopenharmony_ci */ 34862306a36Sopenharmony_ci for (i = 0 ; i < MAX_MACIO_CHIPS; i++) { 34962306a36Sopenharmony_ci if (macio_chips[i].of_node) { 35062306a36Sopenharmony_ci macio_mmio_init_one(&macio_chips[i]); 35162306a36Sopenharmony_ci macio_gpio_init_one(&macio_chips[i]); 35262306a36Sopenharmony_ci } 35362306a36Sopenharmony_ci } 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci /* 35662306a36Sopenharmony_ci * Install handlers for northbridge and direct mapped hwclock 35762306a36Sopenharmony_ci * if any. We do not implement the config space access callback 35862306a36Sopenharmony_ci * which is only ever used for functions that we do not call in 35962306a36Sopenharmony_ci * the current driver (enabling/disabling cells in U2, mostly used 36062306a36Sopenharmony_ci * to restore the PCI settings, we do that differently) 36162306a36Sopenharmony_ci */ 36262306a36Sopenharmony_ci if (uninorth_node && uninorth_base) 36362306a36Sopenharmony_ci uninorth_install_pfunc(); 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci DBG("All base functions installed\n"); 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci return 0; 36862306a36Sopenharmony_ci} 36962306a36Sopenharmony_cimachine_arch_initcall(powermac, pmac_pfunc_base_install); 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci#ifdef CONFIG_PM 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci/* Those can be called by pmac_feature. Ultimately, I should use a sysdev 37462306a36Sopenharmony_ci * or a device, but for now, that's good enough until I sort out some 37562306a36Sopenharmony_ci * ordering issues. Also, we do not bother with GPIOs, as so far I yet have 37662306a36Sopenharmony_ci * to see a case where a GPIO function has the on-suspend or on-resume bit 37762306a36Sopenharmony_ci */ 37862306a36Sopenharmony_civoid pmac_pfunc_base_suspend(void) 37962306a36Sopenharmony_ci{ 38062306a36Sopenharmony_ci int i; 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci for (i = 0 ; i < MAX_MACIO_CHIPS; i++) { 38362306a36Sopenharmony_ci if (macio_chips[i].of_node) 38462306a36Sopenharmony_ci pmf_do_functions(macio_chips[i].of_node, NULL, 0, 38562306a36Sopenharmony_ci PMF_FLAGS_ON_SLEEP, NULL); 38662306a36Sopenharmony_ci } 38762306a36Sopenharmony_ci if (uninorth_node) 38862306a36Sopenharmony_ci pmf_do_functions(uninorth_node, NULL, 0, 38962306a36Sopenharmony_ci PMF_FLAGS_ON_SLEEP, NULL); 39062306a36Sopenharmony_ci if (unin_hwclock) 39162306a36Sopenharmony_ci pmf_do_functions(unin_hwclock, NULL, 0, 39262306a36Sopenharmony_ci PMF_FLAGS_ON_SLEEP, NULL); 39362306a36Sopenharmony_ci} 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_civoid pmac_pfunc_base_resume(void) 39662306a36Sopenharmony_ci{ 39762306a36Sopenharmony_ci int i; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci if (unin_hwclock) 40062306a36Sopenharmony_ci pmf_do_functions(unin_hwclock, NULL, 0, 40162306a36Sopenharmony_ci PMF_FLAGS_ON_WAKE, NULL); 40262306a36Sopenharmony_ci if (uninorth_node) 40362306a36Sopenharmony_ci pmf_do_functions(uninorth_node, NULL, 0, 40462306a36Sopenharmony_ci PMF_FLAGS_ON_WAKE, NULL); 40562306a36Sopenharmony_ci for (i = 0 ; i < MAX_MACIO_CHIPS; i++) { 40662306a36Sopenharmony_ci if (macio_chips[i].of_node) 40762306a36Sopenharmony_ci pmf_do_functions(macio_chips[i].of_node, NULL, 0, 40862306a36Sopenharmony_ci PMF_FLAGS_ON_WAKE, NULL); 40962306a36Sopenharmony_ci } 41062306a36Sopenharmony_ci} 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci#endif /* CONFIG_PM */ 413