File Index
Files and directories
Sign in
FILE

pinctrl-stm32-hdp.c

File preview with syntax highlighting.

linux-6.19.14/drivers/pinctrl/stm32/pinctrl-stm32-hdp.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (C) STMicroelectronics 2025 - All Rights Reserved
  4 * Author: Clément Le Goffic <clement.legoffic@foss.st.com> for STMicroelectronics.
  5 */
  6#include <linux/bits.h>
  7#include <linux/clk.h>
  8#include <linux/gpio/driver.h>
  9#include <linux/gpio/generic.h>
 10#include <linux/io.h>
 11#include <linux/of.h>
 12#include <linux/of_device.h>
 13#include <linux/pinctrl/consumer.h>
 14#include <linux/pinctrl/pinconf-generic.h>
 15#include <linux/pinctrl/pinctrl.h>
 16#include <linux/pinctrl/pinmux.h>
 17#include <linux/platform_device.h>
 18#include <linux/pm.h>
 19
 20#include "../core.h"
 21
 22#define DRIVER_NAME		"stm32_hdp"
 23#define HDP_CTRL_ENABLE		1
 24#define HDP_CTRL_DISABLE	0
 25
 26#define HDP_CTRL		0x000
 27#define HDP_MUX			0x004
 28#define HDP_VAL			0x010
 29#define HDP_GPOSET		0x014
 30#define HDP_GPOCLR		0x018
 31#define HDP_GPOVAL		0x01c
 32#define HDP_VERR		0x3f4
 33#define HDP_IPIDR		0x3f8
 34#define HDP_SIDR		0x3fc
 35
 36#define HDP_MUX_SHIFT(n)	((n) * 4)
 37#define HDP_MUX_MASK(n)		(GENMASK(3, 0) << HDP_MUX_SHIFT(n))
 38#define HDP_MUX_GPOVAL(n)	(0xf << HDP_MUX_SHIFT(n))
 39
 40#define HDP_PIN			8
 41#define HDP_FUNC		16
 42#define HDP_FUNC_TOTAL		(HDP_PIN * HDP_FUNC)
 43
 44struct stm32_hdp {
 45	struct device *dev;
 46	void __iomem *base;
 47	struct clk *clk;
 48	struct pinctrl_dev *pctl_dev;
 49	struct gpio_generic_chip gpio_chip;
 50	u32 mux_conf;
 51	u32 gposet_conf;
 52	const char * const *func_name;
 53};
 54
 55static const struct pinctrl_pin_desc stm32_hdp_pins[] = {
 56	PINCTRL_PIN(0, "HDP0"),
 57	PINCTRL_PIN(1, "HDP1"),
 58	PINCTRL_PIN(2, "HDP2"),
 59	PINCTRL_PIN(3, "HDP3"),
 60	PINCTRL_PIN(4, "HDP4"),
 61	PINCTRL_PIN(5, "HDP5"),
 62	PINCTRL_PIN(6, "HDP6"),
 63	PINCTRL_PIN(7, "HDP7"),
 64};
 65
 66static const char * const func_name_mp13[] = {
 67	//HDP0 functions:
 68	"pwr_pwrwake_sys",
 69	"pwr_stop_forbidden",
 70	"pwr_stdby_wakeup",
 71	"pwr_encomp_vddcore",
 72	"bsec_out_sec_niden",
 73	"aiec_sys_wakeup",
 74	"none",
 75	"none",
 76	"ddrctrl_lp_req",
 77	"pwr_ddr_ret_enable_n",
 78	"dts_clk_ptat",
 79	"none",
 80	"sram3ctrl_tamp_erase_act",
 81	"none",
 82	"none",
 83	"gpoval0",
 84	//HDP1 functions:
 85	"pwr_sel_vth_vddcpu",
 86	"pwr_mpu_ram_lowspeed",
 87	"ca7_naxierrirq",
 88	"pwr_okin_mr",
 89	"bsec_out_sec_dbgen",
 90	"aiec_c1_wakeup",
 91	"rcc_pwrds_mpu",
 92	"none",
 93	"ddrctrl_dfi_ctrlupd_req",
 94	"ddrctrl_cactive_ddrc_asr",
 95	"none",
 96	"none",
 97	"sram3ctrl_hw_erase_act",
 98	"nic400_s0_bready",
 99	"none",
100	"gpoval1",
101	//HDP2 functions:
102	"pwr_pwrwake_mpu",
103	"pwr_mpu_clock_disable_ack",
104	"ca7_ndbgreset_i",
105	"none",
106	"bsec_in_rstcore_n",
107	"bsec_out_sec_bsc_dis",
108	"none",
109	"none",
110	"ddrctrl_dfi_init_complete",
111	"ddrctrl_perf_op_is_refresh",
112	"ddrctrl_gskp_dfi_lp_req",
113	"none",
114	"sram3ctrl_sw_erase_act",
115	"nic400_s0_bvalid",
116	"none",
117	"gpoval2",
118	//HDP3 functions:
119	"pwr_sel_vth_vddcore",
120	"pwr_mpu_clock_disable_req",
121	"ca7_npmuirq0",
122	"ca7_nfiqout0",
123	"bsec_out_sec_dftlock",
124	"bsec_out_sec_jtag_dis",
125	"rcc_pwrds_sys",
126	"sram3ctrl_tamp_erase_req",
127	"ddrctrl_stat_ddrc_reg_selfref_type0",
128	"none",
129	"dts_valobus1_0",
130	"dts_valobus2_0",
131	"tamp_potential_tamp_erfcfg",
132	"nic400_s0_wready",
133	"nic400_s0_rready",
134	"gpoval3",
135	//HDP4 functions:
136	"none",
137	"pwr_stop2_active",
138	"ca7_nl2reset_i",
139	"ca7_npreset_varm_i",
140	"bsec_out_sec_dften",
141	"bsec_out_sec_dbgswenable",
142	"eth1_out_pmt_intr_o",
143	"eth2_out_pmt_intr_o",
144	"ddrctrl_stat_ddrc_reg_selfref_type1",
145	"ddrctrl_cactive_0",
146	"dts_valobus1_1",
147	"dts_valobus2_1",
148	"tamp_nreset_sram_ercfg",
149	"nic400_s0_wlast",
150	"nic400_s0_rlast",
151	"gpoval4",
152	//HDP5 functions:
153	"ca7_standbywfil2",
154	"pwr_vth_vddcore_ack",
155	"ca7_ncorereset_i",
156	"ca7_nirqout0",
157	"bsec_in_pwrok",
158	"bsec_out_sec_deviceen",
159	"eth1_out_lpi_intr_o",
160	"eth2_out_lpi_intr_o",
161	"ddrctrl_cactive_ddrc",
162	"ddrctrl_wr_credit_cnt",
163	"dts_valobus1_2",
164	"dts_valobus2_2",
165	"pka_pka_itamp_out",
166	"nic400_s0_wvalid",
167	"nic400_s0_rvalid",
168	"gpoval5",
169	//HDP6 functions:
170	"ca7_standbywfe0",
171	"pwr_vth_vddcpu_ack",
172	"ca7_evento",
173	"none",
174	"bsec_in_tamper_det",
175	"bsec_out_sec_spniden",
176	"eth1_out_mac_speed_o1",
177	"eth2_out_mac_speed_o1",
178	"ddrctrl_csysack_ddrc",
179	"ddrctrl_lpr_credit_cnt",
180	"dts_valobus1_3",
181	"dts_valobus2_3",
182	"saes_tamper_out",
183	"nic400_s0_awready",
184	"nic400_s0_arready",
185	"gpoval6",
186	//HDP7 functions:
187	"ca7_standbywfi0",
188	"pwr_rcc_vcpu_rdy",
189	"ca7_eventi",
190	"ca7_dbgack0",
191	"bsec_out_fuse_ok",
192	"bsec_out_sec_spiden",
193	"eth1_out_mac_speed_o0",
194	"eth2_out_mac_speed_o0",
195	"ddrctrl_csysreq_ddrc",
196	"ddrctrl_hpr_credit_cnt",
197	"dts_valobus1_4",
198	"dts_valobus2_4",
199	"rng_tamper_out",
200	"nic400_s0_awavalid",
201	"nic400_s0_aravalid",
202	"gpoval7",
203};
204
205static const char * const func_name_mp15[] = {
206	//HDP0 functions:
207	"pwr_pwrwake_sys",
208	"cm4_sleepdeep",
209	"pwr_stdby_wkup",
210	"pwr_encomp_vddcore",
211	"bsec_out_sec_niden",
212	"none",
213	"rcc_cm4_sleepdeep",
214	"gpu_dbg7",
215	"ddrctrl_lp_req",
216	"pwr_ddr_ret_enable_n",
217	"dts_clk_ptat",
218	"none",
219	"none",
220	"none",
221	"none",
222	"gpoval0",
223	//HDP1 functions:
224	"pwr_pwrwake_mcu",
225	"cm4_halted",
226	"ca7_naxierrirq",
227	"pwr_okin_mr",
228	"bsec_out_sec_dbgen",
229	"exti_sys_wakeup",
230	"rcc_pwrds_mpu",
231	"gpu_dbg6",
232	"ddrctrl_dfi_ctrlupd_req",
233	"ddrctrl_cactive_ddrc_asr",
234	"none",
235	"none",
236	"none",
237	"none",
238	"none",
239	"gpoval1",
240	//HDP2 functions:
241	"pwr_pwrwake_mpu",
242	"cm4_rxev",
243	"ca7_npmuirq1",
244	"ca7_nfiqout1",
245	"bsec_in_rstcore_n",
246	"exti_c2_wakeup",
247	"rcc_pwrds_mcu",
248	"gpu_dbg5",
249	"ddrctrl_dfi_init_complete",
250	"ddrctrl_perf_op_is_refresh",
251	"ddrctrl_gskp_dfi_lp_req",
252	"none",
253	"none",
254	"none",
255	"none",
256	"gpoval2",
257	//HDP3 functions:
258	"pwr_sel_vth_vddcore",
259	"cm4_txev",
260	"ca7_npmuirq0",
261	"ca7_nfiqout0",
262	"bsec_out_sec_dftlock",
263	"exti_c1_wakeup",
264	"rcc_pwrds_sys",
265	"gpu_dbg4",
266	"ddrctrl_stat_ddrc_reg_selfref_type0",
267	"ddrctrl_cactive_1",
268	"dts_valobus1_0",
269	"dts_valobus2_0",
270	"none",
271	"none",
272	"none",
273	"gpoval3",
274	//HDP4 functions:
275	"pwr_mpu_pdds_not_cstbydis",
276	"cm4_sleeping",
277	"ca7_nreset1",
278	"ca7_nirqout1",
279	"bsec_out_sec_dften",
280	"bsec_out_sec_dbgswenable",
281	"eth_out_pmt_intr_o",
282	"gpu_dbg3",
283	"ddrctrl_stat_ddrc_reg_selfref_type1",
284	"ddrctrl_cactive_0",
285	"dts_valobus1_1",
286	"dts_valobus2_1",
287	"none",
288	"none",
289	"none",
290	"gpoval4",
291	//HDP5 functions:
292	"ca7_standbywfil2",
293	"pwr_vth_vddcore_ack",
294	"ca7_nreset0",
295	"ca7_nirqout0",
296	"bsec_in_pwrok",
297	"bsec_out_sec_deviceen",
298	"eth_out_lpi_intr_o",
299	"gpu_dbg2",
300	"ddrctrl_cactive_ddrc",
301	"ddrctrl_wr_credit_cnt",
302	"dts_valobus1_2",
303	"dts_valobus2_2",
304	"none",
305	"none",
306	"none",
307	"gpoval5",
308	//HDP6 functions:
309	"ca7_standbywfi1",
310	"ca7_standbywfe1",
311	"ca7_evento",
312	"ca7_dbgack1",
313	"none",
314	"bsec_out_sec_spniden",
315	"eth_out_mac_speed_o1",
316	"gpu_dbg1",
317	"ddrctrl_csysack_ddrc",
318	"ddrctrl_lpr_credit_cnt",
319	"dts_valobus1_3",
320	"dts_valobus2_3",
321	"none",
322	"none",
323	"none",
324	"gpoval6",
325	//HDP7 functions:
326	"ca7_standbywfi0",
327	"ca7_standbywfe0",
328	"none",
329	"ca7_dbgack0",
330	"bsec_out_fuse_ok",
331	"bsec_out_sec_spiden",
332	"eth_out_mac_speed_o0",
333	"gpu_dbg0",
334	"ddrctrl_csysreq_ddrc",
335	"ddrctrl_hpr_credit_cnt",
336	"dts_valobus1_4",
337	"dts_valobus2_4",
338	"none",
339	"none",
340	"none",
341	"gpoval7"
342};
343
344static const char * const func_name_mp25[] = {
345	//HDP0 functions:
346	"pwr_pwrwake_sys",
347	"cpu2_sleep_deep",
348	"bsec_out_tst_sdr_unlock_or_disable_scan",
349	"bsec_out_nidenm",
350	"bsec_out_nidena",
351	"cpu2_state_0",
352	"rcc_pwrds_sys",
353	"gpu_dbg7",
354	"ddrss_csysreq_ddrc",
355	"ddrss_dfi_phyupd_req",
356	"cpu3_sleep_deep",
357	"d2_gbl_per_clk_bus_req",
358	"pcie_usb_cxpl_debug_info_ei_0",
359	"pcie_usb_cxpl_debug_info_ei_8",
360	"d3_state_0",
361	"gpoval0",
362	//HDP1 functions:
363	"pwr_pwrwake_cpu2",
364	"cpu2_halted",
365	"cpu2_state_1",
366	"bsec_out_dbgenm",
367	"bsec_out_dbgena",
368	"exti1_sys_wakeup",
369	"rcc_pwrds_cpu2",
370	"gpu_dbg6",
371	"ddrss_csysack_ddrc",
372	"ddrss_dfi_phymstr_req",
373	"cpu3_halted",
374	"d2_gbl_per_dma_req",
375	"pcie_usb_cxpl_debug_info_ei_1",
376	"pcie_usb_cxpl_debug_info_ei_9",
377	"d3_state_1",
378	"gpoval1",
379	//HDP2 functions:
380	"pwr_pwrwake_cpu1",
381	"cpu2_rxev",
382	"cpu1_npumirq1",
383	"cpu1_nfiqout1",
384	"bsec_out_shdbgen",
385	"exti1_cpu2_wakeup",
386	"rcc_pwrds_cpu1",
387	"gpu_dbg5",
388	"ddrss_cactive_ddrc",
389	"ddrss_dfi_lp_req",
390	"cpu3_rxev",
391	"hpdma1_clk_bus_req",
392	"pcie_usb_cxpl_debug_info_ei_2",
393	"pcie_usb_cxpl_debug_info_ei_10",
394	"d3_state_2",
395	"gpoval2",
396	//HDP3 functions:
397	"pwr_sel_vth_vddcpu",
398	"cpu2_txev",
399	"cpu1_npumirq0",
400	"cpu1_nfiqout0",
401	"bsec_out_ddbgen",
402	"exti1_cpu1_wakeup",
403	"cpu3_state_0",
404	"gpu_dbg4",
405	"ddrss_mcdcg_en",
406	"ddrss_dfi_freq_0",
407	"cpu3_txev",
408	"hpdma2_clk_bus_req",
409	"pcie_usb_cxpl_debug_info_ei_3",
410	"pcie_usb_cxpl_debug_info_ei_11",
411	"d1_state_0",
412	"gpoval3",
413	//HDP4 functions:
414	"pwr_sel_vth_vddcore",
415	"cpu2_sleeping",
416	"cpu1_evento",
417	"cpu1_nirqout1",
418	"bsec_out_spnidena",
419	"exti2_d3_wakeup",
420	"eth1_out_pmt_intr_o",
421	"gpu_dbg3",
422	"ddrss_dphycg_en",
423	"ddrss_obsp0",
424	"cpu3_sleeping",
425	"hpdma3_clk_bus_req",
426	"pcie_usb_cxpl_debug_info_ei_4",
427	"pcie_usb_cxpl_debug_info_ei_12",
428	"d1_state_1",
429	"gpoval4",
430	//HDP5 functions:
431	"cpu1_standby_wfil2",
432	"none",
433	"none",
434	"cpu1_nirqout0",
435	"bsec_out_spidena",
436	"exti2_cpu3_wakeup",
437	"eth1_out_lpi_intr_o",
438	"gpu_dbg2",
439	"ddrctrl_dfi_init_start",
440	"ddrss_obsp1",
441	"cpu3_state_1",
442	"d3_gbl_per_clk_bus_req",
443	"pcie_usb_cxpl_debug_info_ei_5",
444	"pcie_usb_cxpl_debug_info_ei_13",
445	"d1_state_2",
446	"gpoval5",
447	//HDP6 functions:
448	"cpu1_standby_wfi1",
449	"cpu1_standby_wfe1",
450	"cpu1_halted1",
451	"cpu1_naxierrirq",
452	"bsec_out_spnidenm",
453	"exti2_cpu2_wakeup",
454	"eth2_out_pmt_intr_o",
455	"gpu_dbg1",
456	"ddrss_dfi_init_complete",
457	"ddrss_obsp2",
458	"d2_state_0",
459	"d3_gbl_per_dma_req",
460	"pcie_usb_cxpl_debug_info_ei_6",
461	"pcie_usb_cxpl_debug_info_ei_14",
462	"cpu1_state_0",
463	"gpoval6",
464	//HDP7 functions:
465	"cpu1_standby_wfi0",
466	"cpu1_standby_wfe0",
467	"cpu1_halted0",
468	"none",
469	"bsec_out_spidenm",
470	"exti2_cpu1__wakeup",
471	"eth2_out_lpi_intr_o",
472	"gpu_dbg0",
473	"ddrss_dfi_ctrlupd_req",
474	"ddrss_obsp3",
475	"d2_state_1",
476	"lpdma1_clk_bus_req",
477	"pcie_usb_cxpl_debug_info_ei_7",
478	"pcie_usb_cxpl_debug_info_ei_15",
479	"cpu1_state_1",
480	"gpoval7",
481};
482
483static const char * const stm32_hdp_pins_group[] = {
484	"HDP0",
485	"HDP1",
486	"HDP2",
487	"HDP3",
488	"HDP4",
489	"HDP5",
490	"HDP6",
491	"HDP7"
492};
493
494static int stm32_hdp_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
495{
496	return GPIO_LINE_DIRECTION_OUT;
497}
498
499static int stm32_hdp_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
500{
501	return ARRAY_SIZE(stm32_hdp_pins);
502}
503
504static const char *stm32_hdp_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
505						    unsigned int selector)
506{
507	return stm32_hdp_pins[selector].name;
508}
509
510static int stm32_hdp_pinctrl_get_group_pins(struct pinctrl_dev *pctldev, unsigned int selector,
511					    const unsigned int **pins, unsigned int *num_pins)
512{
513	*pins = &stm32_hdp_pins[selector].number;
514	*num_pins = 1;
515
516	return 0;
517}
518
519static const struct pinctrl_ops stm32_hdp_pinctrl_ops = {
520	.get_groups_count = stm32_hdp_pinctrl_get_groups_count,
521	.get_group_name	  = stm32_hdp_pinctrl_get_group_name,
522	.get_group_pins	  = stm32_hdp_pinctrl_get_group_pins,
523	.dt_node_to_map	  = pinconf_generic_dt_node_to_map_all,
524	.dt_free_map	  = pinconf_generic_dt_free_map,
525};
526
527static int stm32_hdp_pinmux_get_functions_count(struct pinctrl_dev *pctldev)
528{
529	return HDP_FUNC_TOTAL;
530}
531
532static const char *stm32_hdp_pinmux_get_function_name(struct pinctrl_dev *pctldev,
533							  unsigned int selector)
534{
535	struct stm32_hdp *hdp = pinctrl_dev_get_drvdata(pctldev);
536
537	return hdp->func_name[selector];
538}
539
540static int stm32_hdp_pinmux_get_function_groups(struct pinctrl_dev *pctldev, unsigned int selector,
541						const char *const **groups,
542						unsigned int *num_groups)
543{
544	u32 index = selector / HDP_FUNC;
545
546	*groups = &stm32_hdp_pins[index].name;
547	*num_groups = 1;
548
549	return 0;
550}
551
552static int stm32_hdp_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector,
553				    unsigned int group_selector)
554{
555	struct stm32_hdp *hdp = pinctrl_dev_get_drvdata(pctldev);
556
557	unsigned int pin = stm32_hdp_pins[group_selector].number;
558	u32 mux;
559
560	func_selector %= HDP_FUNC;
561	mux = readl_relaxed(hdp->base + HDP_MUX);
562	mux &= ~HDP_MUX_MASK(pin);
563	mux |= func_selector << HDP_MUX_SHIFT(pin);
564
565	writel_relaxed(mux, hdp->base + HDP_MUX);
566	hdp->mux_conf = mux;
567
568	return 0;
569}
570
571static const struct pinmux_ops stm32_hdp_pinmux_ops = {
572	.get_functions_count = stm32_hdp_pinmux_get_functions_count,
573	.get_function_name   = stm32_hdp_pinmux_get_function_name,
574	.get_function_groups = stm32_hdp_pinmux_get_function_groups,
575	.set_mux	     = stm32_hdp_pinmux_set_mux,
576	.gpio_set_direction  = NULL,
577};
578
579static const struct pinctrl_desc stm32_hdp_pdesc = {
580	.name	 = DRIVER_NAME,
581	.pins	 = stm32_hdp_pins,
582	.npins	 = ARRAY_SIZE(stm32_hdp_pins),
583	.pctlops = &stm32_hdp_pinctrl_ops,
584	.pmxops	 = &stm32_hdp_pinmux_ops,
585	.owner	 = THIS_MODULE,
586};
587
588static const struct of_device_id stm32_hdp_of_match[] = {
589	{
590		.compatible = "st,stm32mp131-hdp",
591		.data = &func_name_mp13,
592	},
593	{
594		.compatible = "st,stm32mp151-hdp",
595		.data = &func_name_mp15,
596	},
597	{
598		.compatible = "st,stm32mp251-hdp",
599		.data = &func_name_mp25,
600	},
601	{}
602};
603MODULE_DEVICE_TABLE(of, stm32_hdp_of_match);
604
605static int stm32_hdp_probe(struct platform_device *pdev)
606{
607	struct gpio_generic_chip_config config;
608	struct device *dev = &pdev->dev;
609	struct stm32_hdp *hdp;
610	u8 version;
611	int err;
612
613	hdp = devm_kzalloc(dev, sizeof(*hdp), GFP_KERNEL);
614	if (!hdp)
615		return -ENOMEM;
616	hdp->dev = dev;
617
618	platform_set_drvdata(pdev, hdp);
619
620	hdp->base = devm_platform_ioremap_resource(pdev, 0);
621	if (IS_ERR(hdp->base))
622		return PTR_ERR(hdp->base);
623
624	hdp->func_name = of_device_get_match_data(dev);
625	if (!hdp->func_name)
626		return dev_err_probe(dev, -ENODEV, "No function name provided\n");
627
628	hdp->clk = devm_clk_get_enabled(dev, NULL);
629	if (IS_ERR(hdp->clk))
630		return dev_err_probe(dev, PTR_ERR(hdp->clk), "No HDP clock provided\n");
631
632	err = devm_pinctrl_register_and_init(dev, &stm32_hdp_pdesc, hdp, &hdp->pctl_dev);
633	if (err)
634		return dev_err_probe(dev, err, "Failed to register pinctrl\n");
635
636	err = pinctrl_enable(hdp->pctl_dev);
637	if (err)
638		return dev_err_probe(dev, err, "Failed to enable pinctrl\n");
639
640	hdp->gpio_chip.gc.get_direction = stm32_hdp_gpio_get_direction;
641	hdp->gpio_chip.gc.ngpio	     = ARRAY_SIZE(stm32_hdp_pins);
642	hdp->gpio_chip.gc.can_sleep     = true;
643	hdp->gpio_chip.gc.names	     = stm32_hdp_pins_group;
644
645	config = (struct gpio_generic_chip_config) {
646		.dev = dev,
647		.sz = 4,
648		.dat = hdp->base + HDP_GPOVAL,
649		.set = hdp->base + HDP_GPOSET,
650		.clr = hdp->base + HDP_GPOCLR,
651		.flags = GPIO_GENERIC_NO_INPUT,
652	};
653
654	err = gpio_generic_chip_init(&hdp->gpio_chip, &config);
655	if (err)
656		return dev_err_probe(dev, err, "Failed to init the generic GPIO chip\n");
657
658	err = devm_gpiochip_add_data(dev, &hdp->gpio_chip.gc, hdp);
659	if (err)
660		return dev_err_probe(dev, err, "Failed to add gpiochip\n");
661
662	writel_relaxed(HDP_CTRL_ENABLE, hdp->base + HDP_CTRL);
663
664	version = readl_relaxed(hdp->base + HDP_VERR);
665	dev_dbg(dev, "STM32 HDP version %u.%u initialized\n", version >> 4, version & 0x0f);
666
667	return 0;
668}
669
670static void stm32_hdp_remove(struct platform_device *pdev)
671{
672	struct stm32_hdp *hdp = platform_get_drvdata(pdev);
673
674	writel_relaxed(HDP_CTRL_DISABLE, hdp->base + HDP_CTRL);
675}
676
677static int stm32_hdp_suspend(struct device *dev)
678{
679	struct stm32_hdp *hdp = dev_get_drvdata(dev);
680
681	hdp->gposet_conf = readl_relaxed(hdp->base + HDP_GPOSET);
682
683	pinctrl_pm_select_sleep_state(dev);
684
685	clk_disable_unprepare(hdp->clk);
686
687	return 0;
688}
689
690static int stm32_hdp_resume(struct device *dev)
691{
692	struct stm32_hdp *hdp = dev_get_drvdata(dev);
693	int err;
694
695	err = clk_prepare_enable(hdp->clk);
696	if (err) {
697		dev_err(dev, "Failed to prepare_enable clk (%d)\n", err);
698		return err;
699	}
700
701	writel_relaxed(HDP_CTRL_ENABLE, hdp->base + HDP_CTRL);
702	writel_relaxed(hdp->gposet_conf, hdp->base + HDP_GPOSET);
703	writel_relaxed(hdp->mux_conf, hdp->base + HDP_MUX);
704
705	pinctrl_pm_select_default_state(dev);
706
707	return 0;
708}
709
710static DEFINE_SIMPLE_DEV_PM_OPS(stm32_hdp_pm_ops, stm32_hdp_suspend, stm32_hdp_resume);
711
712static struct platform_driver stm32_hdp_driver = {
713	.probe = stm32_hdp_probe,
714	.remove = stm32_hdp_remove,
715	.driver = {
716		.name = DRIVER_NAME,
717		.pm = pm_sleep_ptr(&stm32_hdp_pm_ops),
718		.of_match_table = stm32_hdp_of_match,
719	}
720};
721
722module_platform_driver(stm32_hdp_driver);
723
724MODULE_AUTHOR("Clément Le Goffic");
725MODULE_DESCRIPTION("STMicroelectronics STM32 Hardware Debug Port driver");
726MODULE_LICENSE("GPL");
~/ Read-only file preview.