diff options
-rw-r--r-- | Documentation/devicetree/bindings/tty/serial/sccnxp-serial.txt | 53 | ||||
-rw-r--r-- | drivers/tty/serial/sccnxp.c | 46 | ||||
-rw-r--r-- | include/linux/platform_data/serial-sccnxp.h | 6 |
3 files changed, 93 insertions, 12 deletions
diff --git a/Documentation/devicetree/bindings/tty/serial/sccnxp-serial.txt b/Documentation/devicetree/bindings/tty/serial/sccnxp-serial.txt new file mode 100644 index 000000000000..d18b1698133e --- /dev/null +++ b/Documentation/devicetree/bindings/tty/serial/sccnxp-serial.txt | |||
@@ -0,0 +1,53 @@ | |||
1 | * NXP (Philips) SCC+++(SCN+++) serial driver | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: Should be "nxp,<ictype>". The supported ICs include sc2681, | ||
5 | sc2691, sc2692, sc2891, sc2892, sc28202, sc68681 and sc68692. | ||
6 | - reg: Address and length of the register set for the device. | ||
7 | - interrupts: Should contain the interrupt number. If omitted, | ||
8 | polling mode will be used instead, so "poll-interval" property should | ||
9 | be populated in this case. | ||
10 | |||
11 | Optional properties: | ||
12 | - clocks: Phandle to input clock. If omitted, default IC frequency will be | ||
13 | used instead. | ||
14 | - poll-interval: Poll interval time in nanoseconds. | ||
15 | - vcc-supply: The regulator supplying the VCC to drive the chip. | ||
16 | - nxp,sccnxp-io-cfg: Array contains values for the emulated modem signals. | ||
17 | The number of values depends on the UART-number in the selected chip. | ||
18 | Each value should be composed according to the following rules: | ||
19 | (LINE1 << SIGNAL1) | ... | (LINEX << SIGNALX), where: | ||
20 | LINE - VALUE: | ||
21 | OP0 - 1 | ||
22 | OP1 - 2 | ||
23 | OP2 - 3 | ||
24 | OP3 - 4 | ||
25 | OP4 - 5 | ||
26 | OP5 - 6 | ||
27 | OP6 - 7 | ||
28 | OP7 - 8 | ||
29 | IP0 - 9 | ||
30 | IP1 - 10 | ||
31 | IP2 - 11 | ||
32 | IP3 - 12 | ||
33 | IP4 - 13 | ||
34 | IP5 - 14 | ||
35 | IP6 - 15 | ||
36 | SIGNAL - VALUE: | ||
37 | DTR - 0 | ||
38 | RTS - 4 | ||
39 | DSR - 8 | ||
40 | CTS - 12 | ||
41 | DCD - 16 | ||
42 | RNG - 20 | ||
43 | DIR - 24 | ||
44 | |||
45 | Example (Dual UART with direction control on OP0 & OP1): | ||
46 | sc2892@10100000 { | ||
47 | compatible = "nxp,sc2892"; | ||
48 | reg = <0x10100000 0x10>; | ||
49 | poll-interval = <10000>; | ||
50 | clocks = <&sc2892_clk>; | ||
51 | vcc-supply = <&sc2892_reg>; | ||
52 | nxp,sccnxp-io-cfg = <0x01000000 0x02000000>; | ||
53 | }; | ||
diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c index 49e9bbfe6cab..67f73d1a8e7b 100644 --- a/drivers/tty/serial/sccnxp.c +++ b/drivers/tty/serial/sccnxp.c | |||
@@ -20,6 +20,8 @@ | |||
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/device.h> | 21 | #include <linux/device.h> |
22 | #include <linux/console.h> | 22 | #include <linux/console.h> |
23 | #include <linux/of.h> | ||
24 | #include <linux/of_device.h> | ||
23 | #include <linux/serial_core.h> | 25 | #include <linux/serial_core.h> |
24 | #include <linux/serial.h> | 26 | #include <linux/serial.h> |
25 | #include <linux/io.h> | 27 | #include <linux/io.h> |
@@ -853,10 +855,25 @@ static const struct platform_device_id sccnxp_id_table[] = { | |||
853 | }; | 855 | }; |
854 | MODULE_DEVICE_TABLE(platform, sccnxp_id_table); | 856 | MODULE_DEVICE_TABLE(platform, sccnxp_id_table); |
855 | 857 | ||
858 | static const struct of_device_id sccnxp_dt_id_table[] = { | ||
859 | { .compatible = "nxp,sc2681", .data = &sc2681, }, | ||
860 | { .compatible = "nxp,sc2691", .data = &sc2691, }, | ||
861 | { .compatible = "nxp,sc2692", .data = &sc2692, }, | ||
862 | { .compatible = "nxp,sc2891", .data = &sc2891, }, | ||
863 | { .compatible = "nxp,sc2892", .data = &sc2892, }, | ||
864 | { .compatible = "nxp,sc28202", .data = &sc28202, }, | ||
865 | { .compatible = "nxp,sc68681", .data = &sc68681, }, | ||
866 | { .compatible = "nxp,sc68692", .data = &sc68692, }, | ||
867 | { } | ||
868 | }; | ||
869 | MODULE_DEVICE_TABLE(of, sccnxp_dt_id_table); | ||
870 | |||
856 | static int sccnxp_probe(struct platform_device *pdev) | 871 | static int sccnxp_probe(struct platform_device *pdev) |
857 | { | 872 | { |
858 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 873 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
859 | struct sccnxp_pdata *pdata = dev_get_platdata(&pdev->dev); | 874 | struct sccnxp_pdata *pdata = dev_get_platdata(&pdev->dev); |
875 | const struct of_device_id *of_id = | ||
876 | of_match_device(sccnxp_dt_id_table, &pdev->dev); | ||
860 | int i, ret, uartclk; | 877 | int i, ret, uartclk; |
861 | struct sccnxp_port *s; | 878 | struct sccnxp_port *s; |
862 | void __iomem *membase; | 879 | void __iomem *membase; |
@@ -875,7 +892,22 @@ static int sccnxp_probe(struct platform_device *pdev) | |||
875 | 892 | ||
876 | spin_lock_init(&s->lock); | 893 | spin_lock_init(&s->lock); |
877 | 894 | ||
878 | s->chip = (struct sccnxp_chip *)pdev->id_entry->driver_data; | 895 | if (of_id) { |
896 | s->chip = (struct sccnxp_chip *)of_id->data; | ||
897 | |||
898 | of_property_read_u32(pdev->dev.of_node, "poll-interval", | ||
899 | &s->pdata.poll_time_us); | ||
900 | of_property_read_u32(pdev->dev.of_node, "reg-shift", | ||
901 | &s->pdata.reg_shift); | ||
902 | of_property_read_u32_array(pdev->dev.of_node, | ||
903 | "nxp,sccnxp-io-cfg", | ||
904 | s->pdata.mctrl_cfg, s->chip->nr); | ||
905 | } else { | ||
906 | s->chip = (struct sccnxp_chip *)pdev->id_entry->driver_data; | ||
907 | |||
908 | if (pdata) | ||
909 | memcpy(&s->pdata, pdata, sizeof(struct sccnxp_pdata)); | ||
910 | } | ||
879 | 911 | ||
880 | s->regulator = devm_regulator_get(&pdev->dev, "vcc"); | 912 | s->regulator = devm_regulator_get(&pdev->dev, "vcc"); |
881 | if (!IS_ERR(s->regulator)) { | 913 | if (!IS_ERR(s->regulator)) { |
@@ -906,16 +938,11 @@ static int sccnxp_probe(struct platform_device *pdev) | |||
906 | goto err_out; | 938 | goto err_out; |
907 | } | 939 | } |
908 | 940 | ||
909 | if (pdata) | ||
910 | memcpy(&s->pdata, pdata, sizeof(struct sccnxp_pdata)); | ||
911 | |||
912 | if (s->pdata.poll_time_us) { | 941 | if (s->pdata.poll_time_us) { |
913 | dev_info(&pdev->dev, "Using poll mode, resolution %u usecs\n", | 942 | dev_info(&pdev->dev, "Using poll mode, resolution %u usecs\n", |
914 | s->pdata.poll_time_us); | 943 | s->pdata.poll_time_us); |
915 | s->poll = 1; | 944 | s->poll = 1; |
916 | } | 945 | } else { |
917 | |||
918 | if (!s->poll) { | ||
919 | s->irq = platform_get_irq(pdev, 0); | 946 | s->irq = platform_get_irq(pdev, 0); |
920 | if (s->irq < 0) { | 947 | if (s->irq < 0) { |
921 | dev_err(&pdev->dev, "Missing irq resource data\n"); | 948 | dev_err(&pdev->dev, "Missing irq resource data\n"); |
@@ -1016,8 +1043,9 @@ static int sccnxp_remove(struct platform_device *pdev) | |||
1016 | 1043 | ||
1017 | static struct platform_driver sccnxp_uart_driver = { | 1044 | static struct platform_driver sccnxp_uart_driver = { |
1018 | .driver = { | 1045 | .driver = { |
1019 | .name = SCCNXP_NAME, | 1046 | .name = SCCNXP_NAME, |
1020 | .owner = THIS_MODULE, | 1047 | .owner = THIS_MODULE, |
1048 | .of_match_table = sccnxp_dt_id_table, | ||
1021 | }, | 1049 | }, |
1022 | .probe = sccnxp_probe, | 1050 | .probe = sccnxp_probe, |
1023 | .remove = sccnxp_remove, | 1051 | .remove = sccnxp_remove, |
diff --git a/include/linux/platform_data/serial-sccnxp.h b/include/linux/platform_data/serial-sccnxp.h index af0c8c3b89ae..98373d6add27 100644 --- a/include/linux/platform_data/serial-sccnxp.h +++ b/include/linux/platform_data/serial-sccnxp.h | |||
@@ -78,11 +78,11 @@ | |||
78 | /* SCCNXP platform data structure */ | 78 | /* SCCNXP platform data structure */ |
79 | struct sccnxp_pdata { | 79 | struct sccnxp_pdata { |
80 | /* Shift for A0 line */ | 80 | /* Shift for A0 line */ |
81 | const u8 reg_shift; | 81 | u32 reg_shift; |
82 | /* Modem control lines configuration */ | 82 | /* Modem control lines configuration */ |
83 | const u32 mctrl_cfg[SCCNXP_MAX_UARTS]; | 83 | u32 mctrl_cfg[SCCNXP_MAX_UARTS]; |
84 | /* Timer value for polling mode (usecs) */ | 84 | /* Timer value for polling mode (usecs) */ |
85 | const unsigned int poll_time_us; | 85 | u32 poll_time_us; |
86 | }; | 86 | }; |
87 | 87 | ||
88 | #endif | 88 | #endif |