0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #include <linux/kernel.h>
0018 #include <linux/init.h>
0019 #include <linux/module.h>
0020 #include <linux/interrupt.h>
0021 #include <linux/ioport.h>
0022 #include <linux/serial_core.h>
0023 #include <linux/serial_s3c.h>
0024 #include <linux/platform_device.h>
0025 #include <linux/reboot.h>
0026 #include <linux/io.h>
0027 #include <linux/clk/samsung.h>
0028 #include <linux/dma-mapping.h>
0029 #include <linux/irq.h>
0030 #include <linux/gpio.h>
0031 #include <linux/irqchip/arm-vic.h>
0032 #include <clocksource/samsung_pwm.h>
0033
0034 #include <asm/mach/arch.h>
0035 #include <asm/mach/map.h>
0036 #include <asm/system_misc.h>
0037
0038 #include "map.h"
0039 #include "irqs.h"
0040 #include "regs-gpio.h"
0041 #include "gpio-samsung.h"
0042
0043 #include "cpu.h"
0044 #include "devs.h"
0045 #include "pm.h"
0046 #include "gpio-cfg.h"
0047 #include "pwm-core.h"
0048 #include "regs-irqtype.h"
0049 #include "s3c64xx.h"
0050 #include "irq-uart-s3c64xx.h"
0051
0052
0053 static unsigned long xtal_f __ro_after_init = 12000000;
0054 static unsigned long xusbxti_f __ro_after_init = 48000000;
0055
0056 void __init s3c64xx_set_xtal_freq(unsigned long freq)
0057 {
0058 xtal_f = freq;
0059 }
0060
0061 void __init s3c64xx_set_xusbxti_freq(unsigned long freq)
0062 {
0063 xusbxti_f = freq;
0064 }
0065
0066
0067
0068 static void __init s3c64xx_init_uarts(struct s3c2410_uartcfg *cfg, int no)
0069 {
0070 s3c24xx_init_uartdevs("s3c6400-uart", s3c64xx_uart_resources, cfg, no);
0071 }
0072
0073
0074
0075 static const char name_s3c6400[] = "S3C6400";
0076 static const char name_s3c6410[] = "S3C6410";
0077
0078 static struct cpu_table cpu_ids[] __initdata = {
0079 {
0080 .idcode = S3C6400_CPU_ID,
0081 .idmask = S3C64XX_CPU_MASK,
0082 .map_io = s3c6400_map_io,
0083 .init_uarts = s3c64xx_init_uarts,
0084 .init = s3c6400_init,
0085 .name = name_s3c6400,
0086 }, {
0087 .idcode = S3C6410_CPU_ID,
0088 .idmask = S3C64XX_CPU_MASK,
0089 .map_io = s3c6410_map_io,
0090 .init_uarts = s3c64xx_init_uarts,
0091 .init = s3c6410_init,
0092 .name = name_s3c6410,
0093 },
0094 };
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104 #define UART_OFFS (S3C_PA_UART & 0xfffff)
0105
0106 static struct map_desc s3c_iodesc[] __initdata = {
0107 {
0108 .virtual = (unsigned long)S3C_VA_SYS,
0109 .pfn = __phys_to_pfn(S3C64XX_PA_SYSCON),
0110 .length = SZ_4K,
0111 .type = MT_DEVICE,
0112 }, {
0113 .virtual = (unsigned long)S3C_VA_MEM,
0114 .pfn = __phys_to_pfn(S3C64XX_PA_SROM),
0115 .length = SZ_4K,
0116 .type = MT_DEVICE,
0117 }, {
0118 .virtual = (unsigned long)(S3C_VA_UART + UART_OFFS),
0119 .pfn = __phys_to_pfn(S3C_PA_UART),
0120 .length = SZ_4K,
0121 .type = MT_DEVICE,
0122 }, {
0123 .virtual = (unsigned long)VA_VIC0,
0124 .pfn = __phys_to_pfn(S3C64XX_PA_VIC0),
0125 .length = SZ_16K,
0126 .type = MT_DEVICE,
0127 }, {
0128 .virtual = (unsigned long)VA_VIC1,
0129 .pfn = __phys_to_pfn(S3C64XX_PA_VIC1),
0130 .length = SZ_16K,
0131 .type = MT_DEVICE,
0132 }, {
0133 .virtual = (unsigned long)S3C_VA_TIMER,
0134 .pfn = __phys_to_pfn(S3C_PA_TIMER),
0135 .length = SZ_16K,
0136 .type = MT_DEVICE,
0137 }, {
0138 .virtual = (unsigned long)S3C64XX_VA_GPIO,
0139 .pfn = __phys_to_pfn(S3C64XX_PA_GPIO),
0140 .length = SZ_4K,
0141 .type = MT_DEVICE,
0142 }, {
0143 .virtual = (unsigned long)S3C64XX_VA_MODEM,
0144 .pfn = __phys_to_pfn(S3C64XX_PA_MODEM),
0145 .length = SZ_4K,
0146 .type = MT_DEVICE,
0147 }, {
0148 .virtual = (unsigned long)S3C_VA_WATCHDOG,
0149 .pfn = __phys_to_pfn(S3C64XX_PA_WATCHDOG),
0150 .length = SZ_4K,
0151 .type = MT_DEVICE,
0152 }, {
0153 .virtual = (unsigned long)S3C_VA_USB_HSPHY,
0154 .pfn = __phys_to_pfn(S3C64XX_PA_USB_HSPHY),
0155 .length = SZ_1K,
0156 .type = MT_DEVICE,
0157 },
0158 };
0159
0160 static struct bus_type s3c64xx_subsys = {
0161 .name = "s3c64xx-core",
0162 .dev_name = "s3c64xx-core",
0163 };
0164
0165 static struct device s3c64xx_dev = {
0166 .bus = &s3c64xx_subsys,
0167 };
0168
0169 static struct samsung_pwm_variant s3c64xx_pwm_variant = {
0170 .bits = 32,
0171 .div_base = 0,
0172 .has_tint_cstat = true,
0173 .tclk_mask = (1 << 7) | (1 << 6) | (1 << 5),
0174 };
0175
0176 void __init s3c64xx_set_timer_source(unsigned int event, unsigned int source)
0177 {
0178 s3c64xx_pwm_variant.output_mask = BIT(SAMSUNG_PWM_NUM) - 1;
0179 s3c64xx_pwm_variant.output_mask &= ~(BIT(event) | BIT(source));
0180 }
0181
0182 void __init s3c64xx_timer_init(void)
0183 {
0184 unsigned int timer_irqs[SAMSUNG_PWM_NUM] = {
0185 IRQ_TIMER0_VIC, IRQ_TIMER1_VIC, IRQ_TIMER2_VIC,
0186 IRQ_TIMER3_VIC, IRQ_TIMER4_VIC,
0187 };
0188
0189 samsung_pwm_clocksource_init(S3C_VA_TIMER,
0190 timer_irqs, &s3c64xx_pwm_variant);
0191 }
0192
0193
0194
0195 void __init s3c64xx_init_io(struct map_desc *mach_desc, int size)
0196 {
0197
0198 iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc));
0199 iotable_init(mach_desc, size);
0200
0201
0202 s3c64xx_init_cpu();
0203
0204 s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
0205
0206 samsung_pwm_set_platdata(&s3c64xx_pwm_variant);
0207 }
0208
0209 static __init int s3c64xx_dev_init(void)
0210 {
0211
0212 if (of_have_populated_dt() || !soc_is_s3c64xx())
0213 return 0;
0214
0215 subsys_system_register(&s3c64xx_subsys, NULL);
0216 return device_register(&s3c64xx_dev);
0217 }
0218 core_initcall(s3c64xx_dev_init);
0219
0220
0221
0222
0223
0224
0225 #define IRQ_VIC0_RESUME (1 << (IRQ_RTC_TIC - IRQ_VIC0_BASE))
0226 #define IRQ_VIC1_RESUME (1 << (IRQ_RTC_ALARM - IRQ_VIC1_BASE) | \
0227 1 << (IRQ_PENDN - IRQ_VIC1_BASE) | \
0228 1 << (IRQ_HSMMC0 - IRQ_VIC1_BASE) | \
0229 1 << (IRQ_HSMMC1 - IRQ_VIC1_BASE) | \
0230 1 << (IRQ_HSMMC2 - IRQ_VIC1_BASE))
0231
0232 void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid)
0233 {
0234 s3c64xx_clk_init(NULL, xtal_f, xusbxti_f, soc_is_s3c6400(), S3C_VA_SYS);
0235
0236 printk(KERN_DEBUG "%s: initialising interrupts\n", __func__);
0237
0238
0239 vic_init(VA_VIC0, IRQ_VIC0_BASE, vic0_valid, IRQ_VIC0_RESUME);
0240 vic_init(VA_VIC1, IRQ_VIC1_BASE, vic1_valid, IRQ_VIC1_RESUME);
0241 }
0242
0243 #define eint_offset(irq) ((irq) - IRQ_EINT(0))
0244 #define eint_irq_to_bit(irq) ((u32)(1 << eint_offset(irq)))
0245
0246 static inline void s3c_irq_eint_mask(struct irq_data *data)
0247 {
0248 u32 mask;
0249
0250 mask = __raw_readl(S3C64XX_EINT0MASK);
0251 mask |= (u32)data->chip_data;
0252 __raw_writel(mask, S3C64XX_EINT0MASK);
0253 }
0254
0255 static void s3c_irq_eint_unmask(struct irq_data *data)
0256 {
0257 u32 mask;
0258
0259 mask = __raw_readl(S3C64XX_EINT0MASK);
0260 mask &= ~((u32)data->chip_data);
0261 __raw_writel(mask, S3C64XX_EINT0MASK);
0262 }
0263
0264 static inline void s3c_irq_eint_ack(struct irq_data *data)
0265 {
0266 __raw_writel((u32)data->chip_data, S3C64XX_EINT0PEND);
0267 }
0268
0269 static void s3c_irq_eint_maskack(struct irq_data *data)
0270 {
0271
0272 s3c_irq_eint_mask(data);
0273 s3c_irq_eint_ack(data);
0274 }
0275
0276 static int s3c_irq_eint_set_type(struct irq_data *data, unsigned int type)
0277 {
0278 int offs = eint_offset(data->irq);
0279 int pin, pin_val;
0280 int shift;
0281 u32 ctrl, mask;
0282 u32 newvalue = 0;
0283 void __iomem *reg;
0284
0285 if (offs > 27)
0286 return -EINVAL;
0287
0288 if (offs <= 15)
0289 reg = S3C64XX_EINT0CON0;
0290 else
0291 reg = S3C64XX_EINT0CON1;
0292
0293 switch (type) {
0294 case IRQ_TYPE_NONE:
0295 printk(KERN_WARNING "No edge setting!\n");
0296 break;
0297
0298 case IRQ_TYPE_EDGE_RISING:
0299 newvalue = S3C2410_EXTINT_RISEEDGE;
0300 break;
0301
0302 case IRQ_TYPE_EDGE_FALLING:
0303 newvalue = S3C2410_EXTINT_FALLEDGE;
0304 break;
0305
0306 case IRQ_TYPE_EDGE_BOTH:
0307 newvalue = S3C2410_EXTINT_BOTHEDGE;
0308 break;
0309
0310 case IRQ_TYPE_LEVEL_LOW:
0311 newvalue = S3C2410_EXTINT_LOWLEV;
0312 break;
0313
0314 case IRQ_TYPE_LEVEL_HIGH:
0315 newvalue = S3C2410_EXTINT_HILEV;
0316 break;
0317
0318 default:
0319 printk(KERN_ERR "No such irq type %d", type);
0320 return -1;
0321 }
0322
0323 if (offs <= 15)
0324 shift = (offs / 2) * 4;
0325 else
0326 shift = ((offs - 16) / 2) * 4;
0327 mask = 0x7 << shift;
0328
0329 ctrl = __raw_readl(reg);
0330 ctrl &= ~mask;
0331 ctrl |= newvalue << shift;
0332 __raw_writel(ctrl, reg);
0333
0334
0335
0336 if (offs < 16) {
0337 pin = S3C64XX_GPN(offs);
0338 pin_val = S3C_GPIO_SFN(2);
0339 } else if (offs < 23) {
0340 pin = S3C64XX_GPL(offs + 8 - 16);
0341 pin_val = S3C_GPIO_SFN(3);
0342 } else {
0343 pin = S3C64XX_GPM(offs - 23);
0344 pin_val = S3C_GPIO_SFN(3);
0345 }
0346
0347 s3c_gpio_cfgpin(pin, pin_val);
0348
0349 return 0;
0350 }
0351
0352 static struct irq_chip s3c_irq_eint = {
0353 .name = "s3c-eint",
0354 .irq_mask = s3c_irq_eint_mask,
0355 .irq_unmask = s3c_irq_eint_unmask,
0356 .irq_mask_ack = s3c_irq_eint_maskack,
0357 .irq_ack = s3c_irq_eint_ack,
0358 .irq_set_type = s3c_irq_eint_set_type,
0359 .irq_set_wake = s3c_irqext_wake,
0360 };
0361
0362
0363
0364
0365
0366
0367
0368 static inline void s3c_irq_demux_eint(unsigned int start, unsigned int end)
0369 {
0370 u32 status = __raw_readl(S3C64XX_EINT0PEND);
0371 u32 mask = __raw_readl(S3C64XX_EINT0MASK);
0372 unsigned int irq;
0373
0374 status &= ~mask;
0375 status >>= start;
0376 status &= (1 << (end - start + 1)) - 1;
0377
0378 for (irq = IRQ_EINT(start); irq <= IRQ_EINT(end); irq++) {
0379 if (status & 1)
0380 generic_handle_irq(irq);
0381
0382 status >>= 1;
0383 }
0384 }
0385
0386 static void s3c_irq_demux_eint0_3(struct irq_desc *desc)
0387 {
0388 s3c_irq_demux_eint(0, 3);
0389 }
0390
0391 static void s3c_irq_demux_eint4_11(struct irq_desc *desc)
0392 {
0393 s3c_irq_demux_eint(4, 11);
0394 }
0395
0396 static void s3c_irq_demux_eint12_19(struct irq_desc *desc)
0397 {
0398 s3c_irq_demux_eint(12, 19);
0399 }
0400
0401 static void s3c_irq_demux_eint20_27(struct irq_desc *desc)
0402 {
0403 s3c_irq_demux_eint(20, 27);
0404 }
0405
0406 static int __init s3c64xx_init_irq_eint(void)
0407 {
0408 int irq;
0409
0410
0411 if (of_have_populated_dt() || !soc_is_s3c64xx())
0412 return -ENODEV;
0413
0414 for (irq = IRQ_EINT(0); irq <= IRQ_EINT(27); irq++) {
0415 irq_set_chip_and_handler(irq, &s3c_irq_eint, handle_level_irq);
0416 irq_set_chip_data(irq, (void *)eint_irq_to_bit(irq));
0417 irq_clear_status_flags(irq, IRQ_NOREQUEST);
0418 }
0419
0420 irq_set_chained_handler(IRQ_EINT0_3, s3c_irq_demux_eint0_3);
0421 irq_set_chained_handler(IRQ_EINT4_11, s3c_irq_demux_eint4_11);
0422 irq_set_chained_handler(IRQ_EINT12_19, s3c_irq_demux_eint12_19);
0423 irq_set_chained_handler(IRQ_EINT20_27, s3c_irq_demux_eint20_27);
0424
0425 return 0;
0426 }
0427 arch_initcall(s3c64xx_init_irq_eint);
0428
0429 #ifndef CONFIG_COMPILE_TEST
0430 #pragma message "The platform is deprecated and scheduled for removal. " \
0431 "Please reach to the maintainers of the platform " \
0432 "and linux-samsung-soc@vger.kernel.org if you still use it." \
0433 "Without such feedback, the platform will be removed after 2024."
0434 #endif