Loading Documentation/powerpc/dts-bindings/fsl/mpic.txt 0 → 100644 +42 −0 Original line number Diff line number Diff line * OpenPIC and its interrupt numbers on Freescale's e500/e600 cores The OpenPIC specification does not specify which interrupt source has to become which interrupt number. This is up to the software implementation of the interrupt controller. The only requirement is that every interrupt source has to have an unique interrupt number / vector number. To accomplish this the current implementation assigns the number zero to the first source, the number one to the second source and so on until all interrupt sources have their unique number. Usually the assigned vector number equals the interrupt number mentioned in the documentation for a given core / CPU. This is however not true for the e500 cores (MPC85XX CPUs) where the documentation distinguishes between internal and external interrupt sources and starts counting at zero for both of them. So what to write for external interrupt source X or internal interrupt source Y into the device tree? Here is an example: The memory map for the interrupt controller in the MPC8544[0] shows, that the first interrupt source starts at 0x5_0000 (PIC Register Address Map-Interrupt Source Configuration Registers). This source becomes the number zero therefore: External interrupt 0 = interrupt number 0 External interrupt 1 = interrupt number 1 External interrupt 2 = interrupt number 2 ... Every interrupt number allocates 0x20 bytes register space. So to get its number it is sufficient to shift the lower 16bits to right by five. So for the external interrupt 10 we have: 0x0140 >> 5 = 10 After the external sources, the internal sources follow. The in core I2C controller on the MPC8544 for instance has the internal source number 27. Oo obtain its interrupt number we take the lower 16bits of its memory address (0x5_0560) and shift it right: 0x0560 >> 5 = 43 Therefore the I2C device node for the MPC8544 CPU has to have the interrupt number 43 specified in the device tree. [0] MPC8544E PowerQUICCTM III, Integrated Host Processor Family Reference Manual MPC8544ERM Rev. 1 10/2007 arch/powerpc/boot/dts/mpc8315erdb.dts +27 −0 Original line number Diff line number Diff line Loading @@ -204,6 +204,7 @@ interrupt-parent = <&ipic>; tbi-handle = <&tbi0>; phy-handle = < &phy0 >; fsl,magic-packet; mdio@520 { #address-cells = <1>; Loading Loading @@ -246,6 +247,7 @@ interrupt-parent = <&ipic>; tbi-handle = <&tbi1>; phy-handle = < &phy1 >; fsl,magic-packet; mdio@520 { #address-cells = <1>; Loading Loading @@ -309,6 +311,22 @@ interrupt-parent = <&ipic>; }; gtm1: timer@500 { compatible = "fsl,mpc8315-gtm", "fsl,gtm"; reg = <0x500 0x100>; interrupts = <90 8 78 8 84 8 72 8>; interrupt-parent = <&ipic>; clock-frequency = <133333333>; }; timer@600 { compatible = "fsl,mpc8315-gtm", "fsl,gtm"; reg = <0x600 0x100>; interrupts = <91 8 79 8 85 8 73 8>; interrupt-parent = <&ipic>; clock-frequency = <133333333>; }; /* IPIC * interrupts cell = <intr #, sense> * sense values match linux IORESOURCE_IRQ_* defines: Loading Loading @@ -337,6 +355,15 @@ 0x59 0x8>; interrupt-parent = < &ipic >; }; pmc: power@b00 { compatible = "fsl,mpc8315-pmc", "fsl,mpc8313-pmc", "fsl,mpc8349-pmc"; reg = <0xb00 0x100 0xa00 0x100>; interrupts = <80 8>; interrupt-parent = <&ipic>; fsl,mpc8313-wakeup-timer = <>m1>; }; }; pci0: pci@e0008500 { Loading arch/powerpc/boot/dts/mpc8349emitx.dts +81 −1 Original line number Diff line number Diff line Loading @@ -63,6 +63,24 @@ reg = <0x200 0x100>; }; gpio1: gpio-controller@c00 { #gpio-cells = <2>; compatible = "fsl,mpc8349-gpio"; reg = <0xc00 0x100>; interrupts = <74 0x8>; interrupt-parent = <&ipic>; gpio-controller; }; gpio2: gpio-controller@d00 { #gpio-cells = <2>; compatible = "fsl,mpc8349-gpio"; reg = <0xd00 0x100>; interrupts = <75 0x8>; interrupt-parent = <&ipic>; gpio-controller; }; i2c@3000 { #address-cells = <1>; #size-cells = <0>; Loading @@ -72,6 +90,12 @@ interrupts = <14 0x8>; interrupt-parent = <&ipic>; dfsrr; eeprom: at24@50 { compatible = "st-micro,24c256"; reg = <0x50>; }; }; i2c@3100 { Loading @@ -91,6 +115,25 @@ interrupt-parent = <&ipic>; }; pcf1: iexp@38 { #gpio-cells = <2>; compatible = "ti,pcf8574a"; reg = <0x38>; gpio-controller; }; pcf2: iexp@39 { #gpio-cells = <2>; compatible = "ti,pcf8574a"; reg = <0x39>; gpio-controller; }; spd: at24@51 { compatible = "at24,spd"; reg = <0x51>; }; mcu_pio: mcu@a { #gpio-cells = <2>; compatible = "fsl,mc9s08qg8-mpc8349emitx", Loading Loading @@ -275,6 +318,24 @@ reg = <0x700 0x100>; device_type = "ipic"; }; gpio-leds { compatible = "gpio-leds"; green { label = "Green"; gpios = <&pcf1 0 1>; linux,default-trigger = "heartbeat"; }; yellow { label = "Yellow"; gpios = <&pcf1 1 1>; /* linux,default-trigger = "heartbeat"; */ default-state = "on"; }; }; }; pci0: pci@e0008500 { Loading Loading @@ -331,7 +392,26 @@ compatible = "fsl,mpc8349e-localbus", "fsl,pq2pro-localbus"; reg = <0xe0005000 0xd8>; ranges = <0x3 0x0 0xf0000000 0x210>; ranges = <0x0 0x0 0xfe000000 0x1000000 /* flash */ 0x1 0x0 0xf8000000 0x20000 /* VSC 7385 */ 0x2 0x0 0xf9000000 0x200000 /* exp slot */ 0x3 0x0 0xf0000000 0x210>; /* CF slot */ flash@0,0 { compatible = "cfi-flash"; reg = <0x0 0x0 0x800000>; bank-width = <2>; device-width = <1>; }; flash@0,800000 { #address-cells = <1>; #size-cells = <1>; compatible = "cfi-flash"; reg = <0x0 0x800000 0x800000>; bank-width = <2>; device-width = <1>; }; pata@3,0 { compatible = "fsl,mpc8349emitx-pata", "ata-generic"; Loading arch/powerpc/include/asm/gpio.h +1 −4 Original line number Diff line number Diff line Loading @@ -38,12 +38,9 @@ static inline int gpio_cansleep(unsigned int gpio) return __gpio_cansleep(gpio); } /* * Not implemented, yet. */ static inline int gpio_to_irq(unsigned int gpio) { return -ENOSYS; return __gpio_to_irq(gpio); } static inline int irq_to_gpio(unsigned int irq) Loading arch/powerpc/platforms/83xx/suspend.c +50 −2 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ #define PMCCR1_NEXT_STATE 0x0C /* Next state for power management */ #define PMCCR1_NEXT_STATE_SHIFT 2 #define PMCCR1_CURR_STATE 0x03 /* Current state for power management*/ #define IMMR_SYSCR_OFFSET 0x100 #define IMMR_RCW_OFFSET 0x900 #define RCW_PCI_HOST 0x80000000 Loading Loading @@ -78,6 +79,22 @@ struct mpc83xx_clock { u32 sccr; }; struct mpc83xx_syscr { __be32 sgprl; __be32 sgprh; __be32 spridr; __be32 :32; __be32 spcr; __be32 sicrl; __be32 sicrh; }; struct mpc83xx_saved { u32 sicrl; u32 sicrh; u32 sccr; }; struct pmc_type { int has_deep_sleep; }; Loading @@ -87,6 +104,8 @@ static int has_deep_sleep, deep_sleeping; static int pmc_irq; static struct mpc83xx_pmc __iomem *pmc_regs; static struct mpc83xx_clock __iomem *clock_regs; static struct mpc83xx_syscr __iomem *syscr_regs; static struct mpc83xx_saved saved_regs; static int is_pci_agent, wake_from_pci; static phys_addr_t immrbase; static int pci_pm_state; Loading Loading @@ -137,6 +156,20 @@ static irqreturn_t pmc_irq_handler(int irq, void *dev_id) return ret; } static void mpc83xx_suspend_restore_regs(void) { out_be32(&syscr_regs->sicrl, saved_regs.sicrl); out_be32(&syscr_regs->sicrh, saved_regs.sicrh); out_be32(&clock_regs->sccr, saved_regs.sccr); } static void mpc83xx_suspend_save_regs(void) { saved_regs.sicrl = in_be32(&syscr_regs->sicrl); saved_regs.sicrh = in_be32(&syscr_regs->sicrh); saved_regs.sccr = in_be32(&clock_regs->sccr); } static int mpc83xx_suspend_enter(suspend_state_t state) { int ret = -EAGAIN; Loading Loading @@ -166,6 +199,8 @@ static int mpc83xx_suspend_enter(suspend_state_t state) */ if (deep_sleeping) { mpc83xx_suspend_save_regs(); out_be32(&pmc_regs->mask, PMCER_ALL); out_be32(&pmc_regs->config1, Loading @@ -179,6 +214,8 @@ static int mpc83xx_suspend_enter(suspend_state_t state) in_be32(&pmc_regs->config1) & ~PMCCR1_POWER_OFF); out_be32(&pmc_regs->mask, PMCER_PMCI); mpc83xx_suspend_restore_regs(); } else { out_be32(&pmc_regs->mask, PMCER_PMCI); Loading @@ -194,7 +231,7 @@ out: return ret; } static void mpc83xx_suspend_finish(void) static void mpc83xx_suspend_end(void) { deep_sleeping = 0; } Loading Loading @@ -278,7 +315,7 @@ static struct platform_suspend_ops mpc83xx_suspend_ops = { .valid = mpc83xx_suspend_valid, .begin = mpc83xx_suspend_begin, .enter = mpc83xx_suspend_enter, .finish = mpc83xx_suspend_finish, .end = mpc83xx_suspend_end, }; static int pmc_probe(struct of_device *ofdev, Loading Loading @@ -333,12 +370,23 @@ static int pmc_probe(struct of_device *ofdev, goto out_pmc; } if (has_deep_sleep) { syscr_regs = ioremap(immrbase + IMMR_SYSCR_OFFSET, sizeof(*syscr_regs)); if (!syscr_regs) { ret = -ENOMEM; goto out_syscr; } } if (is_pci_agent) mpc83xx_set_agent(); suspend_set_ops(&mpc83xx_suspend_ops); return 0; out_syscr: iounmap(clock_regs); out_pmc: iounmap(pmc_regs); out: Loading Loading
Documentation/powerpc/dts-bindings/fsl/mpic.txt 0 → 100644 +42 −0 Original line number Diff line number Diff line * OpenPIC and its interrupt numbers on Freescale's e500/e600 cores The OpenPIC specification does not specify which interrupt source has to become which interrupt number. This is up to the software implementation of the interrupt controller. The only requirement is that every interrupt source has to have an unique interrupt number / vector number. To accomplish this the current implementation assigns the number zero to the first source, the number one to the second source and so on until all interrupt sources have their unique number. Usually the assigned vector number equals the interrupt number mentioned in the documentation for a given core / CPU. This is however not true for the e500 cores (MPC85XX CPUs) where the documentation distinguishes between internal and external interrupt sources and starts counting at zero for both of them. So what to write for external interrupt source X or internal interrupt source Y into the device tree? Here is an example: The memory map for the interrupt controller in the MPC8544[0] shows, that the first interrupt source starts at 0x5_0000 (PIC Register Address Map-Interrupt Source Configuration Registers). This source becomes the number zero therefore: External interrupt 0 = interrupt number 0 External interrupt 1 = interrupt number 1 External interrupt 2 = interrupt number 2 ... Every interrupt number allocates 0x20 bytes register space. So to get its number it is sufficient to shift the lower 16bits to right by five. So for the external interrupt 10 we have: 0x0140 >> 5 = 10 After the external sources, the internal sources follow. The in core I2C controller on the MPC8544 for instance has the internal source number 27. Oo obtain its interrupt number we take the lower 16bits of its memory address (0x5_0560) and shift it right: 0x0560 >> 5 = 43 Therefore the I2C device node for the MPC8544 CPU has to have the interrupt number 43 specified in the device tree. [0] MPC8544E PowerQUICCTM III, Integrated Host Processor Family Reference Manual MPC8544ERM Rev. 1 10/2007
arch/powerpc/boot/dts/mpc8315erdb.dts +27 −0 Original line number Diff line number Diff line Loading @@ -204,6 +204,7 @@ interrupt-parent = <&ipic>; tbi-handle = <&tbi0>; phy-handle = < &phy0 >; fsl,magic-packet; mdio@520 { #address-cells = <1>; Loading Loading @@ -246,6 +247,7 @@ interrupt-parent = <&ipic>; tbi-handle = <&tbi1>; phy-handle = < &phy1 >; fsl,magic-packet; mdio@520 { #address-cells = <1>; Loading Loading @@ -309,6 +311,22 @@ interrupt-parent = <&ipic>; }; gtm1: timer@500 { compatible = "fsl,mpc8315-gtm", "fsl,gtm"; reg = <0x500 0x100>; interrupts = <90 8 78 8 84 8 72 8>; interrupt-parent = <&ipic>; clock-frequency = <133333333>; }; timer@600 { compatible = "fsl,mpc8315-gtm", "fsl,gtm"; reg = <0x600 0x100>; interrupts = <91 8 79 8 85 8 73 8>; interrupt-parent = <&ipic>; clock-frequency = <133333333>; }; /* IPIC * interrupts cell = <intr #, sense> * sense values match linux IORESOURCE_IRQ_* defines: Loading Loading @@ -337,6 +355,15 @@ 0x59 0x8>; interrupt-parent = < &ipic >; }; pmc: power@b00 { compatible = "fsl,mpc8315-pmc", "fsl,mpc8313-pmc", "fsl,mpc8349-pmc"; reg = <0xb00 0x100 0xa00 0x100>; interrupts = <80 8>; interrupt-parent = <&ipic>; fsl,mpc8313-wakeup-timer = <>m1>; }; }; pci0: pci@e0008500 { Loading
arch/powerpc/boot/dts/mpc8349emitx.dts +81 −1 Original line number Diff line number Diff line Loading @@ -63,6 +63,24 @@ reg = <0x200 0x100>; }; gpio1: gpio-controller@c00 { #gpio-cells = <2>; compatible = "fsl,mpc8349-gpio"; reg = <0xc00 0x100>; interrupts = <74 0x8>; interrupt-parent = <&ipic>; gpio-controller; }; gpio2: gpio-controller@d00 { #gpio-cells = <2>; compatible = "fsl,mpc8349-gpio"; reg = <0xd00 0x100>; interrupts = <75 0x8>; interrupt-parent = <&ipic>; gpio-controller; }; i2c@3000 { #address-cells = <1>; #size-cells = <0>; Loading @@ -72,6 +90,12 @@ interrupts = <14 0x8>; interrupt-parent = <&ipic>; dfsrr; eeprom: at24@50 { compatible = "st-micro,24c256"; reg = <0x50>; }; }; i2c@3100 { Loading @@ -91,6 +115,25 @@ interrupt-parent = <&ipic>; }; pcf1: iexp@38 { #gpio-cells = <2>; compatible = "ti,pcf8574a"; reg = <0x38>; gpio-controller; }; pcf2: iexp@39 { #gpio-cells = <2>; compatible = "ti,pcf8574a"; reg = <0x39>; gpio-controller; }; spd: at24@51 { compatible = "at24,spd"; reg = <0x51>; }; mcu_pio: mcu@a { #gpio-cells = <2>; compatible = "fsl,mc9s08qg8-mpc8349emitx", Loading Loading @@ -275,6 +318,24 @@ reg = <0x700 0x100>; device_type = "ipic"; }; gpio-leds { compatible = "gpio-leds"; green { label = "Green"; gpios = <&pcf1 0 1>; linux,default-trigger = "heartbeat"; }; yellow { label = "Yellow"; gpios = <&pcf1 1 1>; /* linux,default-trigger = "heartbeat"; */ default-state = "on"; }; }; }; pci0: pci@e0008500 { Loading Loading @@ -331,7 +392,26 @@ compatible = "fsl,mpc8349e-localbus", "fsl,pq2pro-localbus"; reg = <0xe0005000 0xd8>; ranges = <0x3 0x0 0xf0000000 0x210>; ranges = <0x0 0x0 0xfe000000 0x1000000 /* flash */ 0x1 0x0 0xf8000000 0x20000 /* VSC 7385 */ 0x2 0x0 0xf9000000 0x200000 /* exp slot */ 0x3 0x0 0xf0000000 0x210>; /* CF slot */ flash@0,0 { compatible = "cfi-flash"; reg = <0x0 0x0 0x800000>; bank-width = <2>; device-width = <1>; }; flash@0,800000 { #address-cells = <1>; #size-cells = <1>; compatible = "cfi-flash"; reg = <0x0 0x800000 0x800000>; bank-width = <2>; device-width = <1>; }; pata@3,0 { compatible = "fsl,mpc8349emitx-pata", "ata-generic"; Loading
arch/powerpc/include/asm/gpio.h +1 −4 Original line number Diff line number Diff line Loading @@ -38,12 +38,9 @@ static inline int gpio_cansleep(unsigned int gpio) return __gpio_cansleep(gpio); } /* * Not implemented, yet. */ static inline int gpio_to_irq(unsigned int gpio) { return -ENOSYS; return __gpio_to_irq(gpio); } static inline int irq_to_gpio(unsigned int irq) Loading
arch/powerpc/platforms/83xx/suspend.c +50 −2 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ #define PMCCR1_NEXT_STATE 0x0C /* Next state for power management */ #define PMCCR1_NEXT_STATE_SHIFT 2 #define PMCCR1_CURR_STATE 0x03 /* Current state for power management*/ #define IMMR_SYSCR_OFFSET 0x100 #define IMMR_RCW_OFFSET 0x900 #define RCW_PCI_HOST 0x80000000 Loading Loading @@ -78,6 +79,22 @@ struct mpc83xx_clock { u32 sccr; }; struct mpc83xx_syscr { __be32 sgprl; __be32 sgprh; __be32 spridr; __be32 :32; __be32 spcr; __be32 sicrl; __be32 sicrh; }; struct mpc83xx_saved { u32 sicrl; u32 sicrh; u32 sccr; }; struct pmc_type { int has_deep_sleep; }; Loading @@ -87,6 +104,8 @@ static int has_deep_sleep, deep_sleeping; static int pmc_irq; static struct mpc83xx_pmc __iomem *pmc_regs; static struct mpc83xx_clock __iomem *clock_regs; static struct mpc83xx_syscr __iomem *syscr_regs; static struct mpc83xx_saved saved_regs; static int is_pci_agent, wake_from_pci; static phys_addr_t immrbase; static int pci_pm_state; Loading Loading @@ -137,6 +156,20 @@ static irqreturn_t pmc_irq_handler(int irq, void *dev_id) return ret; } static void mpc83xx_suspend_restore_regs(void) { out_be32(&syscr_regs->sicrl, saved_regs.sicrl); out_be32(&syscr_regs->sicrh, saved_regs.sicrh); out_be32(&clock_regs->sccr, saved_regs.sccr); } static void mpc83xx_suspend_save_regs(void) { saved_regs.sicrl = in_be32(&syscr_regs->sicrl); saved_regs.sicrh = in_be32(&syscr_regs->sicrh); saved_regs.sccr = in_be32(&clock_regs->sccr); } static int mpc83xx_suspend_enter(suspend_state_t state) { int ret = -EAGAIN; Loading Loading @@ -166,6 +199,8 @@ static int mpc83xx_suspend_enter(suspend_state_t state) */ if (deep_sleeping) { mpc83xx_suspend_save_regs(); out_be32(&pmc_regs->mask, PMCER_ALL); out_be32(&pmc_regs->config1, Loading @@ -179,6 +214,8 @@ static int mpc83xx_suspend_enter(suspend_state_t state) in_be32(&pmc_regs->config1) & ~PMCCR1_POWER_OFF); out_be32(&pmc_regs->mask, PMCER_PMCI); mpc83xx_suspend_restore_regs(); } else { out_be32(&pmc_regs->mask, PMCER_PMCI); Loading @@ -194,7 +231,7 @@ out: return ret; } static void mpc83xx_suspend_finish(void) static void mpc83xx_suspend_end(void) { deep_sleeping = 0; } Loading Loading @@ -278,7 +315,7 @@ static struct platform_suspend_ops mpc83xx_suspend_ops = { .valid = mpc83xx_suspend_valid, .begin = mpc83xx_suspend_begin, .enter = mpc83xx_suspend_enter, .finish = mpc83xx_suspend_finish, .end = mpc83xx_suspend_end, }; static int pmc_probe(struct of_device *ofdev, Loading Loading @@ -333,12 +370,23 @@ static int pmc_probe(struct of_device *ofdev, goto out_pmc; } if (has_deep_sleep) { syscr_regs = ioremap(immrbase + IMMR_SYSCR_OFFSET, sizeof(*syscr_regs)); if (!syscr_regs) { ret = -ENOMEM; goto out_syscr; } } if (is_pci_agent) mpc83xx_set_agent(); suspend_set_ops(&mpc83xx_suspend_ops); return 0; out_syscr: iounmap(clock_regs); out_pmc: iounmap(pmc_regs); out: Loading