Przeglądaj źródła

Merge pull request #171 in PROCESSOR-SDK/processor-sdk-linux from plsdk-2750 to processor-sdk-linux-4.19.y

* commit '3c4238882bee4590cb0b6d69c3ee4f96ad7efd38':
  net: ethernet: ti: ptp_bc: make pps_mux_sel gpios optional
  net: ethernet: ti: cpts: enhance pps gen/latch operations
  arm: dts: am57[1,2,4]x-idk-pps: break timers into pps_timer and latch_timer
  arm: dts: am57[1,2,4]x-idk-pps: use PIN_OUTPUT_PULLDOWN for off state
  dt-bindings: net : ptp_bc: Document optional parameter pps-sel[0,1]-gpios
  dt-bindings: net: ti-prueth: Document the optional pinctrl parameters for SYNC/LATCH signal
  dt-bindings: net: cpsw: document PPS related optional parameters
Eric Ruei 6 lat temu
rodzic
commit
451dc9ea47

+ 31 - 0
Documentation/devicetree/bindings/net/cpsw.txt

@@ -54,6 +54,18 @@ Optional properties:
 - mac-address		: See ethernet.txt file in the same directory
 - phy_id		: Specifies slave phy id (deprecated, use phy-handle)
 - phy-handle		: See ethernet.txt file in the same directory
+- pps_timer		: phandle, referring to the DM timer for PPS generation
+- latch_timer	: phandle, phandle, referring to the DM timer for PPS latch
+- pinctrl-names	: List of assigned state names,
+				  see pinctrl binding documentation.
+- pinctrl-0: phandle, referring to the PPS signal on configuration node.
+- pinctrl-1: phandle, referring to the PPS signal off configuration node.
+- pinctrl-2: phandle, referring to the PPS ref signal on configuration node.
+- pinctrl-3: phandle, referring to the PPS ref signal off configuration node.
+- pinctrl-4: phandle, referring to the PPS latch signal on configuration node.
+- pinctrl-5: phandle, referring to the PPS latch signal off configuration node.
+- pps-enable-gpios	: GPIO specifier, used to enable PPS signal output
+- ref-enable-gpios	: GPIO specifier, used to enable PPS ref signal output
 
 Slave sub-nodes:
 - fixed-link		: See fixed-link.txt file in the same directory
@@ -126,3 +138,22 @@ Examples:
 			mac-address = [ 00 00 00 00 00 00 ];
 		};
 	};
+
+
+(plus)
+&mac {
+	/* cptr pps1 generator and latch properties */
+	pps_timer = <&timer16>;
+	latch_timer = <&timer15>;
+	pinctrl-names = "pwm_off", "pwm_on", "ref_off", "ref_on",
+			"latch_on", "latch_off";
+	pinctrl-0 = <&pps1_timer16_pwm_off>;
+	pinctrl-1 = <&pps1_timer16_pwm_on>;
+	pinctrl-2 = <&pps1_timer16_pwm2_off>;
+	pinctrl-3 = <&pps1_timer16_pwm2_on>;
+	pinctrl-4 = <&pps1_timer15_latch_on>;
+	pinctrl-5 = <&pps1_timer15_latch_off>;
+
+	pps-enable-gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>;
+	ref-enable-gpios = <&gpio6 19 GPIO_ACTIVE_HIGH>;
+};

+ 19 - 2
Documentation/devicetree/bindings/net/ti-prueth.txt

@@ -32,6 +32,12 @@ Optional properties:
 		     should be "rx_red_hp", "rx_red_lp".
 - interrupts       : should contain an array of PRUSS system event
                      numbers.
+- pinctrl-names	: List of assigned state names,
+				  see pinctrl binding documentation.
+- pinctrl-0: phandle, referring to the SYNC0 signal on configuration node.
+- pinctrl-1: phandle, referring to the SYNC0 signal off configuration node.
+- pinctrl-2: phandle, referring to the LATCH0 signal on configuration node.
+- pinctrl-3: phandle, referring to the LATCH0 signal off configuration node.
 
 Must contain children, one for each of the MAC ports.
 Children must be named ethernet-mii0 and ethernet-mii1.
@@ -67,7 +73,7 @@ Optional properties for children:
 
 Example (am572x-idk board, dual-emac):
 ======================================
-	pruss2_eth {
+	pruss2_eth: pruss2_eth {
 		compatible = "ti,am57-prueth";
 		prus = <&pru2_0>, <&pru2_1>;
 		firmware-name = "ti-pruss/am57xx-pru0-prueth-fw.elf",
@@ -100,7 +106,7 @@ Example (am572x-idk board, dual-emac):
 
 Example (am572x-idk board, single-emac):
 =======================================
-	pruss2_eth {
+	pruss2_eth: pruss2_eth {
 		compatible = "ti,am57-prueth";
 		prus = <&pru2_0>, <&pru2_1>;
 		firmware-name = "",
@@ -120,3 +126,14 @@ Example (am572x-idk board, single-emac):
 			local-mac-address = [00 00 00 00 00 00];
 		};
 	};
+
+
+Example (am572x-idk board, SYNC/LATCH configurations):
+======================================================
+&pruss2_eth {
+	pinctrl-names = "sync0_off", "sync0_on", "latch0_off", "latch0_on";
+	pinctrl-0 = <&pr2_edc_sync0_off>;
+	pinctrl-1 = <&pr2_edc_sync0_on>;
+	pinctrl-2 = <&pr2_edc_latch0_off>;
+	pinctrl-3 = <&pr2_edc_latch0_on>;
+};

+ 12 - 0
Documentation/devicetree/bindings/net/ti-ptp-bc.txt

@@ -4,6 +4,9 @@ Texas Instruments PTP Boundary Clcok Internal Sync Monitor
 Required properties:
 - compatible       : Should be
                         "ti,am57-bc" for AM57xx SoCs
+Optional properties:
+- pps-sel0-gpios	: GPIO specifier, used to select PPS BC mux output
+- pps-sel1-gpios	: GPIO specifier, used to select PPS BC mux output
 
 Example:
 ========
@@ -19,3 +22,12 @@ To enable for am572x-idk, in am572x-idk.dts:
 &ptp_bc {
 	status = "okay";
 };
+
+To enable for am571x-idk-pps, in am572x-idk-pps.dtso:
+
+&ptp_bc {
+	pps-sel0-gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>;
+	pps-sel1-gpios = <&gpio6 7 GPIO_ACTIVE_HIGH>;
+
+	status = "okay";
+};

+ 6 - 5
arch/arm/boot/dts/ti/am571x-idk-pps.dtso

@@ -11,7 +11,8 @@
 
 &mac {
 	/* cptr pps1 generator and latch properties */
-	timers = <&timer16>, <&timer15>;
+	pps_timer = <&timer16>;
+	latch_timer = <&timer15>;
 	pinctrl-names = "pwm_off", "pwm_on", "ref_off", "ref_on",
 			"latch_on", "latch_off";
 	pinctrl-0 = <&pps1_timer16_pwm_off>;
@@ -50,7 +51,7 @@
 
 	pps1_timer16_pwm_off: pps1_timer16_pwm_off {
 		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x36a0, PIN_OUTPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x36a0, PIN_OUTPUT_PULLDOWN | MUX_MODE15)
 		>;
 	};
 
@@ -62,7 +63,7 @@
 
 	pps1_timer16_pwm2_off: pps1_timer16_pwm2_off {
 		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x3680, PIN_OUTPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x3680, PIN_OUTPUT_PULLDOWN | MUX_MODE15)
 		>;
 	};
 
@@ -86,7 +87,7 @@
 
 	pr1_edc_sync0_off: pr1_edc_sync0_off {
 		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x3724, PIN_OUTPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x3724, PIN_OUTPUT_PULLDOWN | MUX_MODE15)
 		>;
 	};
 
@@ -110,7 +111,7 @@
 
 	pr2_edc_sync0_off: pr2_edc_sync0_off {
 		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x3728, PIN_OUTPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x3728, PIN_OUTPUT_PULLDOWN | MUX_MODE15)
 		>;
 	};
 

+ 6 - 5
arch/arm/boot/dts/ti/am572x-idk-pps.dtso

@@ -11,7 +11,8 @@
 
 &mac {
 	/* cptr pps1 generator and latch properties */
-	timers = <&timer16>, <&timer15>;
+	pps_timer = <&timer16>;
+	latch_timer = <&timer15>;
 	pinctrl-names = "pwm_off", "pwm_on", "ref_off", "ref_on",
 			"latch_on", "latch_off";
 	pinctrl-0 = <&pps1_timer16_pwm_off>;
@@ -45,7 +46,7 @@
 
 	pps1_timer16_pwm_off: pps1_timer16_pwm_off {
 		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x36a0, PIN_OUTPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x36a0, PIN_OUTPUT_PULLDOWN | MUX_MODE15)
 		>;
 	};
 
@@ -57,7 +58,7 @@
 
 	pps1_timer16_pwm2_off: pps1_timer16_pwm2_off {
 		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x3680, PIN_OUTPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x3680, PIN_OUTPUT_PULLDOWN | MUX_MODE15)
 		>;
 	};
 
@@ -81,7 +82,7 @@
 
 	pr2_edc_sync0_off: pr2_edc_sync0_off {
 		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x35f8, PIN_OUTPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x35f8, PIN_OUTPUT_PULLDOWN | MUX_MODE15)
 		>;
 	};
 
@@ -105,7 +106,7 @@
 
 	pr2_edc_sync1_off: pr2_edc_sync1_off {
 		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x35fc, PIN_OUTPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x35fc, PIN_OUTPUT_PULLDOWN | MUX_MODE15)
 		>;
 	};
 };

+ 6 - 5
arch/arm/boot/dts/ti/am574x-idk-pps.dtso

@@ -12,7 +12,8 @@
 
 &mac {
 	/* cptr pps1 generator and latch properties */
-	timers = <&timer16>, <&timer15>;
+	pps_timer = <&timer16>;
+	latch_timer = <&timer15>;
 	pinctrl-names = "pwm_off", "pwm_on", "ref_off", "ref_on",
 			"latch_on", "latch_off";
 	pinctrl-0 = <&pps1_timer16_pwm_off>;
@@ -46,7 +47,7 @@
 
 	pps1_timer16_pwm_off: pps1_timer16_pwm_off {
 		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x36a0, PIN_OUTPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x36a0, PIN_OUTPUT_PULLDOWN | MUX_MODE15)
 		>;
 	};
 
@@ -58,7 +59,7 @@
 
 	pps1_timer16_pwm2_off: pps1_timer16_pwm2_off {
 		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x3680, PIN_OUTPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x3680, PIN_OUTPUT_PULLDOWN | MUX_MODE15)
 		>;
 	};
 
@@ -82,7 +83,7 @@
 
 	pr2_edc_sync0_off: pr2_edc_sync0_off {
 		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x35f8, PIN_OUTPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x35f8, PIN_OUTPUT_PULLDOWN | MUX_MODE15)
 		>;
 	};
 
@@ -106,7 +107,7 @@
 
 	pr2_edc_sync1_off: pr2_edc_sync1_off {
 		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x35fc, PIN_OUTPUT | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x35fc, PIN_OUTPUT_PULLDOWN | MUX_MODE15)
 		>;
 	};
 };

+ 249 - 144
drivers/net/ethernet/ti/cpts.c

@@ -440,7 +440,8 @@ static int cpts_proc_pps_ts_events(struct cpts *cpts)
 	list_for_each_safe(this, next, &cpts->events) {
 		event = list_entry(this, struct cpts_event, list);
 		ev = event_type(event);
-		if (ev == CPTS_EV_HW && (cpts_event_port(event) == 4)) {
+		if (ev == CPTS_EV_HW &&
+		    (cpts_event_port(event) == (cpts->pps_hw_index + 1))) {
 			list_del_init(&event->list);
 			list_add(&event->list, &cpts->pool);
 			/* record the timestamp only */
@@ -498,9 +499,11 @@ static int cpts_pps_enable(struct cpts *cpts, int on)
 	if (!on)
 		return 0;
 
-	spin_lock_bh(&cpts->bc_mux_lock);
-	gpio_set_value(cpts->pps_enable_gpio, 1);
-	spin_unlock_bh(&cpts->bc_mux_lock);
+	if (cpts->pps_enable_gpio >= 0) {
+		spin_lock_bh(&cpts->bc_mux_lock);
+		gpio_set_value(cpts->pps_enable_gpio, 1);
+		spin_unlock_bh(&cpts->bc_mux_lock);
+	}
 
 	if (cpts->ref_enable == -1) {
 		cpts_pps_start(cpts);
@@ -542,24 +545,31 @@ static int cpts_pps_init(struct cpts *cpts)
 	cpts->ref_enable = -1;
 	cpts->pps_offset = 0;
 
-	spin_lock_init(&cpts->bc_mux_lock);
+	if (cpts->use_1pps_gen) {
+		spin_lock_init(&cpts->bc_mux_lock);
 
 #ifdef CONFIG_OMAP_DM_TIMER
-	omap_dm_timer_enable(cpts->odt);
-	omap_dm_timer_enable(cpts->odt2);
+		omap_dm_timer_enable(cpts->odt);
 #endif
-	cpts_tmr_init(cpts);
 
-	kthread_init_delayed_work(&cpts->pps_work, cpts_pps_kworker);
-	cpts->pps_kworker = kthread_create_worker(0, "pps0");
+		kthread_init_delayed_work(&cpts->pps_work, cpts_pps_kworker);
+		cpts->pps_kworker = kthread_create_worker(0, "pps0");
 
-	if (IS_ERR(cpts->pps_kworker)) {
-		err = PTR_ERR(cpts->pps_kworker);
-		pr_err("failed to create cpts pps worker %d\n", err);
-		// TBD:add error handling
-		return -1;
+		if (IS_ERR(cpts->pps_kworker)) {
+			err = PTR_ERR(cpts->pps_kworker);
+			pr_err("failed to create cpts pps worker %d\n", err);
+			// TBD:add error handling
+			return -1;
+		}
 	}
 
+#ifdef CONFIG_OMAP_DM_TIMER
+	if (cpts->use_1pps_latch)
+		omap_dm_timer_enable(cpts->odt2);
+#endif
+
+	cpts_tmr_init(cpts);
+
 	return 0;
 }
 
@@ -578,9 +588,11 @@ static void cpts_pps_schedule(struct cpts *cpts)
 			cpts->pps_enable = -1;
 			pinctrl_select_state(cpts->pins,
 					     cpts->pin_state_pwm_off);
-			spin_lock_bh(&cpts->bc_mux_lock);
-			gpio_set_value(cpts->pps_enable_gpio, 0);
-			spin_unlock_bh(&cpts->bc_mux_lock);
+			if (cpts->pps_enable_gpio >= 0) {
+				spin_lock_bh(&cpts->bc_mux_lock);
+				gpio_set_value(cpts->pps_enable_gpio, 0);
+				spin_unlock_bh(&cpts->bc_mux_lock);
+			}
 		}
 
 		if (!cpts->ref_enable) {
@@ -608,7 +620,11 @@ static int cpts_extts_enable(struct cpts *cpts, u32 index, int on)
 	unsigned long flags;
 	u32 v;
 
-	if (index >= cpts->info.n_ext_ts)
+#ifdef CONFIG_TI_1PPS_DM_TIMER
+	if (index >= CPTS_MAX_EXT_TS || index == cpts->pps_hw_index)
+#else
+	if (index >= CPTS_MAX_EXT_TS)
+#endif
 		return -ENXIO;
 
 	if (((cpts->hw_ts_enable & BIT(index)) >> index) == on)
@@ -621,13 +637,17 @@ static int cpts_extts_enable(struct cpts *cpts, u32 index, int on)
 		v |= BIT(8 + index);
 		cpts->hw_ts_enable |= BIT(index);
 #ifdef CONFIG_TI_1PPS_DM_TIMER
-		pinctrl_select_state(cpts->pins, cpts->pin_state_latch_on);
+		if (cpts->use_1pps_latch)
+			pinctrl_select_state(cpts->pins,
+					     cpts->pin_state_latch_on);
 #endif
 	} else {
 		v &= ~BIT(8 + index);
 		cpts->hw_ts_enable &= ~BIT(index);
 #ifdef CONFIG_TI_1PPS_DM_TIMER
-		pinctrl_select_state(cpts->pins, cpts->pin_state_latch_off);
+		if (cpts->use_1pps_latch)
+			pinctrl_select_state(cpts->pins,
+					     cpts->pin_state_latch_off);
 #endif
 	}
 	cpts_write32(cpts, v, control);
@@ -666,16 +686,22 @@ static int cpts_ptp_enable(struct ptp_clock_info *ptp,
 		return cpts_extts_enable(cpts, rq->extts.index, on);
 #ifdef CONFIG_TI_1PPS_DM_TIMER
 	case PTP_CLK_REQ_PPS:
-		if (cpts->use_1pps) {
+		if (cpts->use_1pps_gen) {
 			ok = ptp_bc_clock_sync_enable(cpts->bc_clkid, on);
 			if (!ok) {
 				pr_info("cpts error: bc clk sync pps enable denied\n");
 				return -EBUSY;
 			}
+			return cpts_pps_enable(cpts, on);
+		} else	{
+			return -EOPNOTSUPP;
 		}
-		return cpts_pps_enable(cpts, on);
+
 	case PTP_CLK_REQ_PEROUT:
 		/* this enables a pps for external measurement */
+		if (!cpts->use_1pps_ref)
+			return -EOPNOTSUPP;
+
 		if (rq->perout.index != 0)
 			return -EINVAL;
 
@@ -692,7 +718,7 @@ static int cpts_ptp_enable(struct ptp_clock_info *ptp,
 
 		return cpts_ref_enable(cpts, on);
 	case PTP_CLK_REQ_PPS_OFFSET:
-		if (cpts->use_1pps)
+		if (cpts->use_1pps_gen)
 			cpts->pps_offset = on;
 		return 0;
 #endif
@@ -731,7 +757,7 @@ static const struct ptp_clock_info cpts_info = {
 	.owner		= THIS_MODULE,
 	.name		= "CTPS timer",
 	.max_adj	= 1000000,
-	.n_ext_ts	= 0,
+	.n_ext_ts	= CPTS_MAX_EXT_TS,
 	.n_pins		= 0,
 	.pps		= 0,
 	.adjfreq	= cpts_ptp_adjfreq,
@@ -863,6 +889,13 @@ int cpts_tx_timestamp(struct cpts *cpts, struct sk_buff *skb)
 }
 EXPORT_SYMBOL_GPL(cpts_tx_timestamp);
 
+#ifdef CONFIG_TI_1PPS_DM_TIMER
+static u32 cpts_hw_ts_push_en[4] = {HW1_TS_PUSH_EN,
+				    HW2_TS_PUSH_EN,
+				    HW3_TS_PUSH_EN,
+				    HW4_TS_PUSH_EN};
+#endif
+
 int cpts_register(struct cpts *cpts)
 {
 	int err, i;
@@ -890,14 +923,15 @@ int cpts_register(struct cpts *cpts)
 
 	ptp_schedule_worker(cpts->clock, cpts->ov_check_period);
 #ifdef CONFIG_TI_1PPS_DM_TIMER
-	cpts_write32(cpts, cpts_read32(cpts, control) |
-		     HW4_TS_PUSH_EN, control);
-
-	if (cpts->use_1pps) {
+	if (cpts->use_1pps_gen) {
 		cpts->bc_clkid = ptp_bc_clock_register(PTP_BC_CLOCK_TYPE_GMAC);
 		pr_info("cpts ptp bc clkid %d\n", cpts->bc_clkid);
 		ptp_bc_mux_ctrl_register((void *)cpts, &cpts->bc_mux_lock,
 					 cpts_bc_mux_ctrl);
+		cpts_write32(cpts, cpts_read32(cpts, control) |
+			     cpts_hw_ts_push_en[cpts->pps_hw_index],
+			     control);
+
 	}
 #endif
 	return 0;
@@ -971,46 +1005,32 @@ static void cpts_calc_mult_shift(struct cpts *cpts)
 static int cpts_of_1pps_parse(struct cpts *cpts, struct device_node *node)
 {
 	struct device_node *np = NULL;
-	struct device_node *np2 = NULL;
 	int gpio, ret;
+	u32 prop;
 
-	np = of_parse_phandle(node, "timers", 0);
+	np = of_parse_phandle(node, "pps_timer", 0);
 	if (!np) {
-		dev_err(cpts->dev, "device node lookup for pps timer failed\n");
-		return -ENXIO;
-	}
-
-	np2 = of_parse_phandle(node, "timers", 1);
-	if (!np2) {
-		dev_err(cpts->dev, "device node lookup for pps timer input failed\n");
+		dev_dbg(cpts->dev,
+			"device node lookup for pps timer failed\n");
 		return -ENXIO;
 	}
 
-	cpts->pps_tmr_irqn = of_irq_get(np, 0);
-	if (!cpts->pps_tmr_irqn)
-		dev_err(cpts->dev, "cannot get 1pps timer interrupt number\n");
-
-	cpts->pps_latch_irqn = of_irq_get(np2, 0);
-	if (!cpts->pps_latch_irqn)
-		dev_err(cpts->dev, "cannot get 1pps latch interrupt number\n");
-
 #ifdef CONFIG_OMAP_DM_TIMER
 	cpts->odt = omap_dm_timer_request_by_node(np);
-	cpts->odt2 = omap_dm_timer_request_by_node(np2);
 #endif
-	if (!cpts->odt || !cpts->odt2)
+	if (!cpts->odt)
 		return -EPROBE_DEFER;
 
 	if (IS_ERR(cpts->odt)) {
-		dev_err(cpts->dev, "request for 1pps timer failed: %ld\n",
+		dev_err(cpts->dev, "request for 1pps DM timer failed: %ld\n",
 			PTR_ERR(cpts->odt));
 		return PTR_ERR(cpts->odt);
 	}
 
-	if (IS_ERR(cpts->odt2)) {
-		dev_err(cpts->dev, "request for 1pps timer input failed: %ld\n",
-			PTR_ERR(cpts->odt2));
-		return PTR_ERR(cpts->odt2);
+	cpts->pps_tmr_irqn = of_irq_get(np, 0);
+	if (!cpts->pps_tmr_irqn) {
+		dev_err(cpts->dev, "cannot get 1pps timer interrupt number\n");
+		return -EINVAL;
 	}
 
 	cpts->pins = devm_pinctrl_get(cpts->dev);
@@ -1034,62 +1054,50 @@ static int cpts_of_1pps_parse(struct cpts *cpts, struct device_node *node)
 		return PTR_ERR(cpts->pin_state_pwm_off);
 	}
 
-	cpts->pin_state_latch_on = pinctrl_lookup_state(cpts->pins,
-							"latch_on");
-	if (IS_ERR(cpts->pin_state_latch_on)) {
-		dev_err(cpts->dev, "lookup for latch_on pin state failed: %ld\n",
-			PTR_ERR(cpts->pin_state_latch_on));
-		return PTR_ERR(cpts->pin_state_latch_on);
-	}
-
-	cpts->pin_state_latch_off = pinctrl_lookup_state(cpts->pins,
-							 "latch_off");
-	if (IS_ERR(cpts->pin_state_latch_off)) {
-		dev_err(cpts->dev, "lookup for latch_off pin state failed: %ld\n",
-			PTR_ERR(cpts->pin_state_latch_off));
-		return PTR_ERR(cpts->pin_state_latch_off);
-	}
-
+	/* The 1PPS enable-gpio signal is only optional and therefore it
+	 * may not be provided by DTB.
+	 */
+	cpts->pps_enable_gpio = -1;
 	gpio = of_get_named_gpio(node, "pps-enable-gpios", 0);
 	if (!gpio_is_valid(gpio)) {
-		dev_err(cpts->dev, "failed to parse pps-enable gpio\n");
-		return gpio;
-	}
+		dev_dbg(cpts->dev, "there is no pps-enable gpio\n");
+	} else {
 
-	ret = devm_gpio_request(cpts->dev, gpio, "pps-enable-ctrl");
-	if (ret) {
-		dev_err(cpts->dev, "failed to acquire pps-enable gpio\n");
-		return ret;
+		ret = devm_gpio_request(cpts->dev, gpio, "pps-enable-ctrl");
+		if (ret) {
+			dev_err(cpts->dev,
+				"failed to acquire pps-enable gpio\n");
+			return ret;
+		}
+		cpts->pps_enable_gpio = gpio;
+		gpio_direction_output(gpio, 0);
 	}
-	cpts->pps_enable_gpio = gpio;
-	gpio_direction_output(gpio, 0);
+
+	if (!of_property_read_u32(node, "cpts_pps_hw_event_index", &prop))
+		cpts->pps_hw_index = prop;
+	else
+		cpts->pps_hw_index = CPTS_PPS_HW_INDEX;
+
+	if (cpts->pps_hw_index > CPTS_PPS_HW_INDEX)
+		cpts->pps_hw_index = CPTS_PPS_HW_INDEX;
+
+	dev_dbg(cpts->dev, "cpts pps hw event index = %d\n",
+		cpts->pps_hw_index);
+
+	cpts->use_1pps_gen = true;
 
 	/* The 1PPS reference signal is only optional and therefore the
 	 * corresponding pins may not be provided by DTB.
 	 */
 
-	gpio = of_get_named_gpio(node, "ref-enable-gpios", 0);
-	if (!gpio_is_valid(gpio)) {
-		cpts->ref_enable_gpio = -1;
+	cpts->pin_state_ref_on = pinctrl_lookup_state(cpts->pins,
+						      "ref_on");
+	if (IS_ERR(cpts->pin_state_ref_on)) {
+		dev_notice(cpts->dev,
+			   "lookup for ref_on pin state failed: %ld\n",
+			   PTR_ERR(cpts->pin_state_ref_on));
+		return PTR_ERR(cpts->pin_state_ref_on);
 	} else {
-		ret = devm_gpio_request(cpts->dev, gpio, "ref-enable-ctrl");
-		if (ret) {
-			dev_err(cpts->dev,
-				"failed to acquire ref-enable gpio\n");
-			devm_gpio_free(cpts->dev, cpts->pps_enable_gpio);
-			return ret;
-		}
-		cpts->ref_enable_gpio = gpio;
-		gpio_direction_output(gpio, 1);
-
-		cpts->pin_state_ref_on = pinctrl_lookup_state(cpts->pins,
-							      "ref_on");
-		if (IS_ERR(cpts->pin_state_ref_on)) {
-			dev_err(cpts->dev,
-				"lookup for ref_on pin state failed: %ld\n",
-				PTR_ERR(cpts->pin_state_ref_on));
-			return PTR_ERR(cpts->pin_state_ref_on);
-		}
 
 		cpts->pin_state_ref_off = pinctrl_lookup_state(cpts->pins,
 							       "ref_off");
@@ -1099,6 +1107,83 @@ static int cpts_of_1pps_parse(struct cpts *cpts, struct device_node *node)
 				PTR_ERR(cpts->pin_state_ref_off));
 			return PTR_ERR(cpts->pin_state_ref_off);
 		}
+
+		/* The 1PPS ref-enable-gpio signal is only optional and
+		 * therefore it	 may not be provided by DTB.
+		 */
+		cpts->ref_enable_gpio = -1;
+		gpio = of_get_named_gpio(node, "ref-enable-gpios", 0);
+		if (!gpio_is_valid(gpio)) {
+			dev_dbg(cpts->dev,
+				"there is no ref-enable gpio\n");
+		} else {
+			ret = devm_gpio_request(cpts->dev, gpio,
+						"ref-enable-ctrl");
+			if (ret) {
+				dev_err(cpts->dev,
+					"failed to acquire ref-enable gpio\n");
+				devm_gpio_free(cpts->dev,
+					       cpts->pps_enable_gpio);
+				return ret;
+			}
+			cpts->ref_enable_gpio = gpio;
+			gpio_direction_output(gpio, 1);
+		}
+		cpts->use_1pps_ref = true;
+	}
+
+	return 0;
+}
+
+static int cpts_of_1pps_latch_parse(struct cpts *cpts, struct device_node *node)
+{
+	struct device_node *np2 = NULL;
+
+	np2 = of_parse_phandle(node, "latch_timer", 0);
+	if (!np2) {
+		dev_dbg(cpts->dev,
+			"device node lookup for latch timer input failed\n");
+		return -ENXIO;
+	}
+
+#ifdef CONFIG_OMAP_DM_TIMER
+	cpts->odt2 = omap_dm_timer_request_by_node(np2);
+#endif
+	if (!cpts->odt2)
+		return -EPROBE_DEFER;
+
+	if (IS_ERR(cpts->odt2)) {
+		dev_err(cpts->dev,
+			"request for 1pps latch timer input failed: %ld\n",
+			PTR_ERR(cpts->odt2));
+		return PTR_ERR(cpts->odt2);
+	}
+
+	cpts->pps_latch_irqn = of_irq_get(np2, 0);
+	if (!cpts->pps_latch_irqn)
+		dev_err(cpts->dev, "cannot get 1pps latch interrupt number\n");
+
+	cpts->pins = devm_pinctrl_get(cpts->dev);
+	if (IS_ERR(cpts->pins)) {
+		dev_err(cpts->dev, "request for 1pps pins failed: %ld\n",
+			PTR_ERR(cpts->pins));
+		return PTR_ERR(cpts->pins);
+	}
+
+	cpts->pin_state_latch_on = pinctrl_lookup_state(cpts->pins,
+							"latch_on");
+	if (IS_ERR(cpts->pin_state_latch_on)) {
+		dev_err(cpts->dev, "lookup for latch_on pin state failed: %ld\n",
+			PTR_ERR(cpts->pin_state_latch_on));
+		return PTR_ERR(cpts->pin_state_latch_on);
+	}
+
+	cpts->pin_state_latch_off = pinctrl_lookup_state(cpts->pins,
+							 "latch_off");
+	if (IS_ERR(cpts->pin_state_latch_off)) {
+		dev_err(cpts->dev, "lookup for latch_off pin state failed: %ld\n",
+			PTR_ERR(cpts->pin_state_latch_off));
+		return PTR_ERR(cpts->pin_state_latch_off);
 	}
 
 	return 0;
@@ -1138,7 +1223,11 @@ static int cpts_of_parse(struct cpts *cpts, struct device_node *node)
 	if (ret == -EPROBE_DEFER)
 		return ret;
 
-	cpts->use_1pps = (ret == 0);
+	ret = cpts_of_1pps_latch_parse(cpts, node);
+	if (ret == -EPROBE_DEFER)
+		return ret;
+
+	cpts->use_1pps_latch = (ret == 0);
 #endif
 
 	return 0;
@@ -1213,7 +1302,7 @@ struct cpts *cpts_create(struct device *dev, void __iomem *regs,
 		}
 	}
 
-	if (cpts->use_1pps) {
+	if (cpts->use_1pps_gen || cpts->use_1pps_latch) {
 		ret = cpts_pps_init(cpts);
 
 		if (ret < 0) {
@@ -1223,9 +1312,10 @@ struct cpts *cpts_create(struct device *dev, void __iomem *regs,
 		}
 
 		/* Enable 1PPS related features	*/
-		cpts->info.pps		= 1;
-		cpts->info.n_ext_ts	= CPTS_MAX_LATCH;
-		cpts->info.n_per_out	= (cpts->ref_enable_gpio >= 0) ? 1 : 0;
+		cpts->info.pps		= (cpts->use_1pps_gen) ? 1 : 0;
+		cpts->info.n_ext_ts	= (cpts->use_1pps_gen) ?
+					  CPTS_MAX_EXT_TS - 1 : CPTS_MAX_EXT_TS;
+		cpts->info.n_per_out	= (cpts->use_1pps_ref) ? 1 : 0;
 	}
 #endif
 
@@ -1281,6 +1371,9 @@ static void cpts_bc_mux_ctrl(void *ctx, int enable)
 	struct cpts *cpts = (struct cpts *)ctx;
 	static int state;
 
+	if (cpts->pps_enable_gpio < 0)
+		return;
+
 	if (enable) {
 		if (!state)
 			gpio_set_value(cpts->pps_enable_gpio, 0);
@@ -1369,46 +1462,52 @@ static void cpts_tmr_init(struct cpts *cpts)
 	if (!cpts)
 		return;
 
-	parent = clk_get(&cpts->odt->pdev->dev, "abe_giclk_div");
-	if (IS_ERR(parent)) {
-		pr_err("%s: %s not found\n", __func__, "abe_giclk_div");
-		return;
-	}
+	if (cpts->use_1pps_gen)	{
+		parent = clk_get(&cpts->odt->pdev->dev, "abe_giclk_div");
+		if (IS_ERR(parent)) {
+			pr_err("%s: %s not found\n", __func__, "abe_giclk_div");
+			return;
+		}
 
-	ret = clk_set_parent(cpts->odt->fclk, parent);
-	if (ret < 0)
-		pr_err("%s: failed to set %s as parent\n", __func__,
-		       "abe_giclk_div");
+		ret = clk_set_parent(cpts->odt->fclk, parent);
+		if (ret < 0)
+			pr_err("%s: failed to set %s as parent\n", __func__,
+			       "abe_giclk_div");
 
-	parent = clk_get(&cpts->odt2->pdev->dev, "abe_giclk_div");
-	if (IS_ERR(parent)) {
-		pr_err("%s: %s not found\n", __func__, "abe_giclk_div");
-		return;
-	}
+		/* initialize timer16 for 1pps generator */
+		cpts_tmr_reinit(cpts);
 
-	ret = clk_set_parent(cpts->odt2->fclk, parent);
-	if (ret < 0)
-		pr_err("%s: failed to set %s as parent\n", __func__,
-		       "abe_giclk_div");
+		writel_relaxed(OMAP_TIMER_INT_OVERFLOW, cpts->odt->irq_ena);
+		__omap_dm_timer_write(cpts->odt, OMAP_TIMER_WAKEUP_EN_REG,
+				      OMAP_TIMER_INT_OVERFLOW, 0);
 
-	/* initialize timer16 for 1pps generator */
-	cpts_tmr_reinit(cpts);
+		pinctrl_select_state(cpts->pins, cpts->pin_state_pwm_off);
+		if (cpts->use_1pps_ref)
+			pinctrl_select_state(cpts->pins,
+					     cpts->pin_state_ref_off);
+	}
 
-	/* initialize timer15 for 1pps latch */
-	cpts_latch_tmr_init(cpts);
+	if (cpts->use_1pps_latch) {
+		parent = clk_get(&cpts->odt2->pdev->dev, "abe_giclk_div");
+		if (IS_ERR(parent)) {
+			pr_err("%s: %s not found\n", __func__, "abe_giclk_div");
+			return;
+		}
 
-	writel_relaxed(OMAP_TIMER_INT_OVERFLOW, cpts->odt->irq_ena);
-	__omap_dm_timer_write(cpts->odt, OMAP_TIMER_WAKEUP_EN_REG,
-			      OMAP_TIMER_INT_OVERFLOW, 0);
+		ret = clk_set_parent(cpts->odt2->fclk, parent);
+		if (ret < 0)
+			pr_err("%s: failed to set %s as parent\n", __func__,
+			       "abe_giclk_div");
 
-	writel_relaxed(OMAP_TIMER_INT_CAPTURE, cpts->odt2->irq_ena);
-	__omap_dm_timer_write(cpts->odt2, OMAP_TIMER_WAKEUP_EN_REG,
-			      OMAP_TIMER_INT_CAPTURE, 0);
+		/* initialize timer15 for 1pps latch */
+		cpts_latch_tmr_init(cpts);
 
-	pinctrl_select_state(cpts->pins, cpts->pin_state_pwm_off);
-	if (cpts->ref_enable_gpio >= 0)
-		pinctrl_select_state(cpts->pins, cpts->pin_state_ref_off);
-	pinctrl_select_state(cpts->pins, cpts->pin_state_latch_off);
+		writel_relaxed(OMAP_TIMER_INT_CAPTURE, cpts->odt2->irq_ena);
+		__omap_dm_timer_write(cpts->odt2, OMAP_TIMER_WAKEUP_EN_REG,
+				      OMAP_TIMER_INT_CAPTURE, 0);
+
+		pinctrl_select_state(cpts->pins, cpts->pin_state_latch_off);
+	}
 }
 
 static inline void cpts_turn_on_off_1pps_output(struct cpts *cpts, u64 ts)
@@ -1417,15 +1516,18 @@ static inline void cpts_turn_on_off_1pps_output(struct cpts *cpts, u64 ts)
 		if (cpts->pps_enable == 1) {
 			pinctrl_select_state(cpts->pins,
 					     cpts->pin_state_pwm_on);
-			spin_lock_bh(&cpts->bc_mux_lock);
-			gpio_set_value(cpts->pps_enable_gpio, 0);
-			spin_unlock_bh(&cpts->bc_mux_lock);
+			if (cpts->pps_enable_gpio >= 0) {
+				spin_lock_bh(&cpts->bc_mux_lock);
+				gpio_set_value(cpts->pps_enable_gpio, 0);
+				spin_unlock_bh(&cpts->bc_mux_lock);
+			}
 		}
 
 		if (cpts->ref_enable == 1) {
 			pinctrl_select_state(cpts->pins,
 					     cpts->pin_state_ref_on);
-			gpio_set_value(cpts->ref_enable_gpio, 0);
+			if (cpts->ref_enable_gpio >= 0)
+				gpio_set_value(cpts->ref_enable_gpio, 0);
 		}
 
 		pr_debug("1pps on at %llu\n", ts);
@@ -1433,15 +1535,18 @@ static inline void cpts_turn_on_off_1pps_output(struct cpts *cpts, u64 ts)
 		if (cpts->pps_enable == 1) {
 			pinctrl_select_state(cpts->pins,
 					     cpts->pin_state_pwm_off);
-			spin_lock_bh(&cpts->bc_mux_lock);
-			gpio_set_value(cpts->pps_enable_gpio, 1);
-			spin_unlock_bh(&cpts->bc_mux_lock);
+			if (cpts->pps_enable_gpio >= 0) {
+				spin_lock_bh(&cpts->bc_mux_lock);
+				gpio_set_value(cpts->pps_enable_gpio, 1);
+				spin_unlock_bh(&cpts->bc_mux_lock);
+			}
 		}
 
 		if (cpts->ref_enable == 1) {
 			pinctrl_select_state(cpts->pins,
 					     cpts->pin_state_ref_off);
-			gpio_set_value(cpts->ref_enable_gpio, 1);
+			if (cpts->ref_enable_gpio >= 0)
+				gpio_set_value(cpts->ref_enable_gpio, 1);
 		}
 	}
 }

+ 6 - 4
drivers/net/ethernet/ti/cpts.h

@@ -114,9 +114,8 @@ enum {
 #define CPTS_EVENT_RX_TX_TIMEOUT 20 /* ms */
 #define CPTS_EVENT_HWSTAMP_TIMEOUT 200 /* ms */
 
-#ifdef CONFIG_TI_1PPS_DM_TIMER
-#define CPTS_MAX_LATCH	3
-#endif
+#define CPTS_MAX_EXT_TS 4
+#define CPTS_PPS_HW_INDEX 3
 
 struct cpts_event {
 	struct list_head list;
@@ -152,8 +151,11 @@ struct cpts {
 	u32 caps;
 
 #ifdef CONFIG_TI_1PPS_DM_TIMER
-	u8 use_1pps;
+	u8 use_1pps_gen;
+	u8 use_1pps_latch;
+	u8 use_1pps_ref;
 	u8 pps_latch_receive;
+	int pps_hw_index;
 	int pps_enable;
 	int pps_state;
 	int pps_latch_state;

+ 17 - 6
drivers/net/ethernet/ti/ptp_bc.c

@@ -53,6 +53,10 @@ static void ptp_bc_free_clk_id(int clkid)
 
 static void ptp_bc_clock_pps_mux_reset(void)
 {
+	if (bc_clk_pps_mux_sel0_gpio < 0 ||
+	    bc_clk_pps_mux_sel1_gpio < 0)
+		return;
+
 	if (bc_mux_ctrl_handler) {
 		spin_lock_bh(bc_mux_lock);
 		bc_mux_ctrl_handler(bc_mux_ctrl_ctx, false);
@@ -74,6 +78,10 @@ static void ptp_bc_clock_pps_mux_sel(int clkid)
 		return;
 	}
 
+	if (bc_clk_pps_mux_sel0_gpio < 0 ||
+	    bc_clk_pps_mux_sel1_gpio < 0)
+		return;
+
 	if (bc_mux_ctrl_handler) {
 		spin_lock_bh(bc_mux_lock);
 		bc_mux_ctrl_handler(bc_mux_ctrl_ctx, false);
@@ -207,14 +215,18 @@ EXPORT_SYMBOL_GPL(ptp_bc_mux_ctrl_register);
 static int ptp_bc_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
-	int ret, gpio;
+	int ret = 0, gpio;
 
 	spin_lock_init(&bc_sync_lock);
 	bc_clk_sync_enabled = 0;
 	bc_clocks_registered = 0;
+	bc_clk_pps_mux_sel0_gpio = -1;
+	bc_clk_pps_mux_sel1_gpio = -1;
+	ptp_bc_initialized  = true;
+
 	gpio = of_get_named_gpio(np, "pps-sel0-gpios", 0);
-	if (!gpio_is_valid(bc_clk_pps_mux_sel0_gpio)) {
-		dev_err(&pdev->dev, "failed to parse pps-sel0 gpio\n");
+	if (!gpio_is_valid(gpio)) {
+		dev_dbg(&pdev->dev, "failed to parse pps-sel0 gpio\n");
 		return -EINVAL;
 	}
 
@@ -227,8 +239,8 @@ static int ptp_bc_probe(struct platform_device *pdev)
 	bc_clk_pps_mux_sel0_gpio = gpio;
 
 	gpio = of_get_named_gpio(np, "pps-sel1-gpios", 0);
-	if (!gpio_is_valid(bc_clk_pps_mux_sel1_gpio)) {
-		dev_err(&pdev->dev, "failed to parse pps-sel1 gpio\n");
+	if (!gpio_is_valid(gpio)) {
+		dev_dbg(&pdev->dev, "failed to parse pps-sel1 gpio\n");
 		devm_gpio_free(&pdev->dev, bc_clk_pps_mux_sel0_gpio);
 		return -EINVAL;
 	}
@@ -242,7 +254,6 @@ static int ptp_bc_probe(struct platform_device *pdev)
 	gpio_direction_output(gpio, 0);
 	bc_clk_pps_mux_sel1_gpio = gpio;
 
-	ptp_bc_initialized  = true;
 	return 0;
 }