summaryrefslogtreecommitdiff
path: root/drivers/hsi/controllers/omap_ssi.h
blob: 32ced0c8f7894d7645cbc1b9001e5a0c77ade3bb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
/* OMAP SSI internal interface.
 *
 * Copyright (C) 2010 Nokia Corporation. All rights reserved.
 * Copyright (C) 2013 Sebastian Reichel
 *
 * Contact: Carlos Chinea <carlos.chinea@nokia.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 */

#ifndef __LINUX_HSI_OMAP_SSI_H__
#define __LINUX_HSI_OMAP_SSI_H__

#include <linux/device.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/hsi/hsi.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/io.h>

#define SSI_MAX_CHANNELS	8
#define SSI_MAX_GDD_LCH		8
#define SSI_BYTES_TO_FRAMES(x) ((((x) - 1) >> 2) + 1)

#define SSI_WAKE_EN 0

/**
 * struct omap_ssm_ctx - OMAP synchronous serial module (TX/RX) context
 * @mode: Bit transmission mode
 * @channels: Number of channels
 * @framesize: Frame size in bits
 * @timeout: RX frame timeout
 * @divisor: TX divider
 * @arb_mode: Arbitration mode for TX frame (Round robin, priority)
 */
struct omap_ssm_ctx {
	u32	mode;
	u32	channels;
	u32	frame_size;
	union	{
			u32	timeout; /* Rx Only */
			struct	{
					u32	arb_mode;
					u32	divisor;
			}; /* Tx only */
	};
};

/**
 * struct omap_ssi_port - OMAP SSI port data
 * @dev: device associated to the port (HSI port)
 * @pdev: platform device associated to the port
 * @sst_dma: SSI transmitter physical base address
 * @ssr_dma: SSI receiver physical base address
 * @sst_base: SSI transmitter base address
 * @ssr_base: SSI receiver base address
 * @wk_lock: spin lock to serialize access to the wake lines
 * @lock: Spin lock to serialize access to the SSI port
 * @channels: Current number of channels configured (1,2,4 or 8)
 * @txqueue: TX message queues
 * @rxqueue: RX message queues
 * @brkqueue: Queue of incoming HWBREAK requests (FRAME mode)
 * @errqueue: Queue for failed messages
 * @errqueue_work: Delayed Work for failed messages
 * @irq: IRQ number
 * @wake_irq: IRQ number for incoming wake line (-1 if none)
 * @wake_gpio: GPIO number for incoming wake line (-1 if none)
 * @flags: flags to keep track of states
 * @wk_refcount: Reference count for output wake line
 * @work: worker for starting TX
 * @sys_mpu_enable: Context for the interrupt enable register for irq 0
 * @sst: Context for the synchronous serial transmitter
 * @ssr: Context for the synchronous serial receiver
 */
struct omap_ssi_port {
	struct device		*dev;
	struct device           *pdev;
	dma_addr_t		sst_dma;
	dma_addr_t		ssr_dma;
	void __iomem		*sst_base;
	void __iomem		*ssr_base;
	spinlock_t		wk_lock;
	spinlock_t		lock;
	unsigned int		channels;
	struct list_head	txqueue[SSI_MAX_CHANNELS];
	struct list_head	rxqueue[SSI_MAX_CHANNELS];
	struct list_head	brkqueue;
	struct list_head	errqueue;
	struct delayed_work	errqueue_work;
	unsigned int		irq;
	int			wake_irq;
	struct gpio_desc	*wake_gpio;
	bool			wktest:1; /* FIXME: HACK to be removed */
	unsigned long		flags;
	unsigned int		wk_refcount;
	struct work_struct	work;
	/* OMAP SSI port context */
	u32			sys_mpu_enable; /* We use only one irq */
	struct omap_ssm_ctx	sst;
	struct omap_ssm_ctx	ssr;
	u32			loss_count;
	u32			port_id;
#ifdef CONFIG_DEBUG_FS
	struct dentry *dir;
#endif
};

/**
 * struct gdd_trn - GDD transaction data
 * @msg: Pointer to the HSI message being served
 * @sg: Pointer to the current sg entry being served
 */
struct gdd_trn {
	struct hsi_msg		*msg;
	struct scatterlist	*sg;
};

/**
 * struct omap_ssi_controller - OMAP SSI controller data
 * @dev: device associated to the controller (HSI controller)
 * @sys: SSI I/O base address
 * @gdd: GDD I/O base address
 * @fck: SSI functional clock
 * @gdd_irq: IRQ line for GDD
 * @gdd_tasklet: bottom half for DMA transfers
 * @gdd_trn: Array of GDD transaction data for ongoing GDD transfers
 * @lock: lock to serialize access to GDD
 * @fck_nb: DVFS notfifier block
 * @fck_rate: clock rate
 * @loss_count: To follow if we need to restore context or not
 * @max_speed: Maximum TX speed (Kb/s) set by the clients.
 * @gdd_gcr: SSI GDD saved context
 * @get_loss: Pointer to omap_pm_get_dev_context_loss_count, if any
 * @port: Array of pointers of the ports of the controller
 * @dir: Debugfs SSI root directory
 */
struct omap_ssi_controller {
	struct device		*dev;
	void __iomem		*sys;
	void __iomem		*gdd;
	struct clk		*fck;
	unsigned int		gdd_irq;
	struct tasklet_struct	gdd_tasklet;
	struct gdd_trn		gdd_trn[SSI_MAX_GDD_LCH];
	spinlock_t		lock;
	struct notifier_block	fck_nb;
	unsigned long		fck_rate;
	u32			loss_count;
	u32			max_speed;
	/* OMAP SSI Controller context */
	u32			gdd_gcr;
	int			(*get_loss)(struct device *dev);
	struct omap_ssi_port	**port;
#ifdef CONFIG_DEBUG_FS
	struct dentry *dir;
#endif
};

void omap_ssi_port_update_fclk(struct hsi_controller *ssi,
			       struct omap_ssi_port *omap_port);

extern struct platform_driver ssi_port_pdriver;

#endif /* __LINUX_HSI_OMAP_SSI_H__ */