162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/* OMAP SSI internal interface.
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (C) 2010 Nokia Corporation. All rights reserved.
562306a36Sopenharmony_ci * Copyright (C) 2013 Sebastian Reichel
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Contact: Carlos Chinea <carlos.chinea@nokia.com>
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#ifndef __LINUX_HSI_OMAP_SSI_H__
1162306a36Sopenharmony_ci#define __LINUX_HSI_OMAP_SSI_H__
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/device.h>
1462306a36Sopenharmony_ci#include <linux/module.h>
1562306a36Sopenharmony_ci#include <linux/platform_device.h>
1662306a36Sopenharmony_ci#include <linux/hsi/hsi.h>
1762306a36Sopenharmony_ci#include <linux/gpio/consumer.h>
1862306a36Sopenharmony_ci#include <linux/interrupt.h>
1962306a36Sopenharmony_ci#include <linux/io.h>
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#define SSI_MAX_CHANNELS	8
2262306a36Sopenharmony_ci#define SSI_MAX_GDD_LCH		8
2362306a36Sopenharmony_ci#define SSI_BYTES_TO_FRAMES(x) ((((x) - 1) >> 2) + 1)
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#define SSI_WAKE_EN 0
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci/**
2862306a36Sopenharmony_ci * struct omap_ssm_ctx - OMAP synchronous serial module (TX/RX) context
2962306a36Sopenharmony_ci * @mode: Bit transmission mode
3062306a36Sopenharmony_ci * @channels: Number of channels
3162306a36Sopenharmony_ci * @framesize: Frame size in bits
3262306a36Sopenharmony_ci * @timeout: RX frame timeout
3362306a36Sopenharmony_ci * @divisor: TX divider
3462306a36Sopenharmony_ci * @arb_mode: Arbitration mode for TX frame (Round robin, priority)
3562306a36Sopenharmony_ci */
3662306a36Sopenharmony_cistruct omap_ssm_ctx {
3762306a36Sopenharmony_ci	u32	mode;
3862306a36Sopenharmony_ci	u32	channels;
3962306a36Sopenharmony_ci	u32	frame_size;
4062306a36Sopenharmony_ci	union	{
4162306a36Sopenharmony_ci			u32	timeout; /* Rx Only */
4262306a36Sopenharmony_ci			struct	{
4362306a36Sopenharmony_ci					u32	arb_mode;
4462306a36Sopenharmony_ci					u32	divisor;
4562306a36Sopenharmony_ci			}; /* Tx only */
4662306a36Sopenharmony_ci	};
4762306a36Sopenharmony_ci};
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci/**
5062306a36Sopenharmony_ci * struct omap_ssi_port - OMAP SSI port data
5162306a36Sopenharmony_ci * @dev: device associated to the port (HSI port)
5262306a36Sopenharmony_ci * @pdev: platform device associated to the port
5362306a36Sopenharmony_ci * @sst_dma: SSI transmitter physical base address
5462306a36Sopenharmony_ci * @ssr_dma: SSI receiver physical base address
5562306a36Sopenharmony_ci * @sst_base: SSI transmitter base address
5662306a36Sopenharmony_ci * @ssr_base: SSI receiver base address
5762306a36Sopenharmony_ci * @wk_lock: spin lock to serialize access to the wake lines
5862306a36Sopenharmony_ci * @lock: Spin lock to serialize access to the SSI port
5962306a36Sopenharmony_ci * @channels: Current number of channels configured (1,2,4 or 8)
6062306a36Sopenharmony_ci * @txqueue: TX message queues
6162306a36Sopenharmony_ci * @rxqueue: RX message queues
6262306a36Sopenharmony_ci * @brkqueue: Queue of incoming HWBREAK requests (FRAME mode)
6362306a36Sopenharmony_ci * @errqueue: Queue for failed messages
6462306a36Sopenharmony_ci * @errqueue_work: Delayed Work for failed messages
6562306a36Sopenharmony_ci * @irq: IRQ number
6662306a36Sopenharmony_ci * @wake_irq: IRQ number for incoming wake line (-1 if none)
6762306a36Sopenharmony_ci * @wake_gpio: GPIO number for incoming wake line (-1 if none)
6862306a36Sopenharmony_ci * @flags: flags to keep track of states
6962306a36Sopenharmony_ci * @wk_refcount: Reference count for output wake line
7062306a36Sopenharmony_ci * @work: worker for starting TX
7162306a36Sopenharmony_ci * @sys_mpu_enable: Context for the interrupt enable register for irq 0
7262306a36Sopenharmony_ci * @sst: Context for the synchronous serial transmitter
7362306a36Sopenharmony_ci * @ssr: Context for the synchronous serial receiver
7462306a36Sopenharmony_ci */
7562306a36Sopenharmony_cistruct omap_ssi_port {
7662306a36Sopenharmony_ci	struct device		*dev;
7762306a36Sopenharmony_ci	struct device           *pdev;
7862306a36Sopenharmony_ci	dma_addr_t		sst_dma;
7962306a36Sopenharmony_ci	dma_addr_t		ssr_dma;
8062306a36Sopenharmony_ci	void __iomem		*sst_base;
8162306a36Sopenharmony_ci	void __iomem		*ssr_base;
8262306a36Sopenharmony_ci	spinlock_t		wk_lock;
8362306a36Sopenharmony_ci	spinlock_t		lock;
8462306a36Sopenharmony_ci	unsigned int		channels;
8562306a36Sopenharmony_ci	struct list_head	txqueue[SSI_MAX_CHANNELS];
8662306a36Sopenharmony_ci	struct list_head	rxqueue[SSI_MAX_CHANNELS];
8762306a36Sopenharmony_ci	struct list_head	brkqueue;
8862306a36Sopenharmony_ci	struct list_head	errqueue;
8962306a36Sopenharmony_ci	struct delayed_work	errqueue_work;
9062306a36Sopenharmony_ci	unsigned int		irq;
9162306a36Sopenharmony_ci	int			wake_irq;
9262306a36Sopenharmony_ci	struct gpio_desc	*wake_gpio;
9362306a36Sopenharmony_ci	bool			wktest:1; /* FIXME: HACK to be removed */
9462306a36Sopenharmony_ci	unsigned long		flags;
9562306a36Sopenharmony_ci	unsigned int		wk_refcount;
9662306a36Sopenharmony_ci	struct work_struct	work;
9762306a36Sopenharmony_ci	/* OMAP SSI port context */
9862306a36Sopenharmony_ci	u32			sys_mpu_enable; /* We use only one irq */
9962306a36Sopenharmony_ci	struct omap_ssm_ctx	sst;
10062306a36Sopenharmony_ci	struct omap_ssm_ctx	ssr;
10162306a36Sopenharmony_ci	u32			loss_count;
10262306a36Sopenharmony_ci	u32			port_id;
10362306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
10462306a36Sopenharmony_ci	struct dentry *dir;
10562306a36Sopenharmony_ci#endif
10662306a36Sopenharmony_ci};
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci/**
10962306a36Sopenharmony_ci * struct gdd_trn - GDD transaction data
11062306a36Sopenharmony_ci * @msg: Pointer to the HSI message being served
11162306a36Sopenharmony_ci * @sg: Pointer to the current sg entry being served
11262306a36Sopenharmony_ci */
11362306a36Sopenharmony_cistruct gdd_trn {
11462306a36Sopenharmony_ci	struct hsi_msg		*msg;
11562306a36Sopenharmony_ci	struct scatterlist	*sg;
11662306a36Sopenharmony_ci};
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci/**
11962306a36Sopenharmony_ci * struct omap_ssi_controller - OMAP SSI controller data
12062306a36Sopenharmony_ci * @dev: device associated to the controller (HSI controller)
12162306a36Sopenharmony_ci * @sys: SSI I/O base address
12262306a36Sopenharmony_ci * @gdd: GDD I/O base address
12362306a36Sopenharmony_ci * @fck: SSI functional clock
12462306a36Sopenharmony_ci * @gdd_irq: IRQ line for GDD
12562306a36Sopenharmony_ci * @gdd_tasklet: bottom half for DMA transfers
12662306a36Sopenharmony_ci * @gdd_trn: Array of GDD transaction data for ongoing GDD transfers
12762306a36Sopenharmony_ci * @lock: lock to serialize access to GDD
12862306a36Sopenharmony_ci * @fck_nb: DVFS notfifier block
12962306a36Sopenharmony_ci * @fck_rate: clock rate
13062306a36Sopenharmony_ci * @loss_count: To follow if we need to restore context or not
13162306a36Sopenharmony_ci * @max_speed: Maximum TX speed (Kb/s) set by the clients.
13262306a36Sopenharmony_ci * @gdd_gcr: SSI GDD saved context
13362306a36Sopenharmony_ci * @get_loss: Pointer to omap_pm_get_dev_context_loss_count, if any
13462306a36Sopenharmony_ci * @port: Array of pointers of the ports of the controller
13562306a36Sopenharmony_ci * @dir: Debugfs SSI root directory
13662306a36Sopenharmony_ci */
13762306a36Sopenharmony_cistruct omap_ssi_controller {
13862306a36Sopenharmony_ci	struct device		*dev;
13962306a36Sopenharmony_ci	void __iomem		*sys;
14062306a36Sopenharmony_ci	void __iomem		*gdd;
14162306a36Sopenharmony_ci	struct clk		*fck;
14262306a36Sopenharmony_ci	unsigned int		gdd_irq;
14362306a36Sopenharmony_ci	struct tasklet_struct	gdd_tasklet;
14462306a36Sopenharmony_ci	struct gdd_trn		gdd_trn[SSI_MAX_GDD_LCH];
14562306a36Sopenharmony_ci	spinlock_t		lock;
14662306a36Sopenharmony_ci	struct notifier_block	fck_nb;
14762306a36Sopenharmony_ci	unsigned long		fck_rate;
14862306a36Sopenharmony_ci	u32			loss_count;
14962306a36Sopenharmony_ci	u32			max_speed;
15062306a36Sopenharmony_ci	/* OMAP SSI Controller context */
15162306a36Sopenharmony_ci	u32			gdd_gcr;
15262306a36Sopenharmony_ci	int			(*get_loss)(struct device *dev);
15362306a36Sopenharmony_ci	struct omap_ssi_port	**port;
15462306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
15562306a36Sopenharmony_ci	struct dentry *dir;
15662306a36Sopenharmony_ci#endif
15762306a36Sopenharmony_ci};
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_civoid omap_ssi_port_update_fclk(struct hsi_controller *ssi,
16062306a36Sopenharmony_ci			       struct omap_ssi_port *omap_port);
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ciextern struct platform_driver ssi_port_pdriver;
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci#endif /* __LINUX_HSI_OMAP_SSI_H__ */
165