1 /*
2  * Copyright (c) 2020, Texas Instruments Incorporated
3  * Copyright (c) 2020 Linaro Ltd.
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <zephyr/kernel.h>
9 #include <zephyr/device.h>
10 #include <zephyr/drivers/gpio.h>
11 
12 #include <driverlib/cpu.h>
13 
14 #define GPIO_PORT DT_NODELABEL(gpio0)
15 #define DIO8_PIN  8
16 #define DIO9_PIN  9
17 #define DIO10_PIN 10
18 #define DIO20_PIN 20
19 
20 
21 /*
22  *  ======== CC1352R1_LAUNCHXL_sendExtFlashByte ========
23  */
CC1352R1_LAUNCHXL_sendExtFlashByte(const struct device * dev,uint8_t byte)24 void CC1352R1_LAUNCHXL_sendExtFlashByte(const struct device *dev,
25 					uint8_t byte)
26 {
27 	uint8_t i;
28 
29 	/* SPI Flash CS */
30 	gpio_pin_set(dev, DIO20_PIN, 0);
31 
32 	for (i = 0; i < 8; i++) {
33 		gpio_pin_set(dev, DIO10_PIN, 0); /* SPI Flash CLK */
34 
35 		/* SPI Flash MOSI */
36 		gpio_pin_set(dev, DIO9_PIN, (byte >> (7 - i)) & 0x01);
37 		gpio_pin_set(dev, DIO10_PIN, 1); /* SPI Flash CLK */
38 
39 		/*
40 		 * Waste a few cycles to keep the CLK high for at
41 		 * least 45% of the period.
42 		 * 3 cycles per loop: 8 loops @ 48 Mhz = 0.5 us.
43 		 */
44 		CPUdelay(8);
45 	}
46 
47 	gpio_pin_set(dev, DIO10_PIN, 0);   /* CLK */
48 	gpio_pin_set(dev, DIO20_PIN, 1);   /* CS */
49 
50 	/*
51 	 * Keep CS high at least 40 us
52 	 * 3 cycles per loop: 700 loops @ 48 Mhz ~= 44 us
53 	 */
54 	CPUdelay(700);
55 }
56 
57 /*
58  *  ======== CC1352R1_LAUNCHXL_wakeUpExtFlash ========
59  */
CC1352R1_LAUNCHXL_wakeUpExtFlash(const struct device * dev)60 void CC1352R1_LAUNCHXL_wakeUpExtFlash(const struct device *dev)
61 {
62 	/*
63 	 *  To wake up we need to toggle the chip select at
64 	 *  least 20 ns and ten wait at least 35 us.
65 	 */
66 
67 	/* Toggle chip select for ~20ns to wake ext. flash */
68 	gpio_pin_set(dev, DIO20_PIN, 0);
69 	/* 3 cycles per loop: 1 loop @ 48 Mhz ~= 62 ns */
70 	CPUdelay(1);
71 	gpio_pin_set(dev, DIO20_PIN, 1);
72 	/* 3 cycles per loop: 560 loops @ 48 Mhz ~= 35 us */
73 	CPUdelay(560);
74 }
75 
76 /*
77  *  ======== CC1352R1_LAUNCHXL_shutDownExtFlash ========
78  */
CC1352R1_LAUNCHXL_shutDownExtFlash(void)79 void CC1352R1_LAUNCHXL_shutDownExtFlash(void)
80 {
81 	const struct device *dev;
82 	uint8_t extFlashShutdown = 0xB9;
83 
84 	dev = DEVICE_DT_GET(GPIO_PORT);
85 
86 	if (!device_is_ready(dev)) {
87 		printk("%s: device not ready.\n", dev->name);
88 		return;
89 	}
90 
91 	/* Set SPI Flash CS pin as output */
92 	gpio_pin_configure(dev, DIO20_PIN, GPIO_OUTPUT);
93 	/* Set SPI Flash CLK pin as output */
94 	gpio_pin_configure(dev, DIO10_PIN, GPIO_OUTPUT);
95 	/* Set SPI Flash MOSI pin as output */
96 	gpio_pin_configure(dev, DIO9_PIN, GPIO_OUTPUT);
97 	/* Set SPI Flash MISO pin as input */
98 	gpio_pin_configure(dev, DIO8_PIN, GPIO_INPUT | GPIO_PULL_DOWN);
99 
100 	/*
101 	 *  To be sure we are putting the flash into sleep and not waking it,
102 	 *  we first have to make a wake up call
103 	 */
104 	CC1352R1_LAUNCHXL_wakeUpExtFlash(dev);
105 
106 	CC1352R1_LAUNCHXL_sendExtFlashByte(dev, extFlashShutdown);
107 }
108