mirror of
https://github.com/team-infusion-developers/android_kernel_samsung_msm8976.git
synced 2024-11-01 10:33:27 +00:00
f0cfb2f747
Update the implementation of the pinctrl usage in the driver such that the driver can use several groups of pins simultaneously, as required by the TSC HW. Change-Id: I9d3350a183c47d4eca9a0628ab17fa55fff2fb06 Signed-off-by: Anat Etzion-Fuchs <aetzion@codeaurora.org>
398 lines
14 KiB
Text
398 lines
14 KiB
Text
Introduction
|
|
============
|
|
|
|
TSC Driver
|
|
|
|
The TSC (Transport Stream Controller) is a hardware block used in products such
|
|
as smart TVs, Set-top boxes and digital media adapters, and is responsible for
|
|
two main functionalities:
|
|
|
|
1. Mux function: enabling the routing of MPEG-2 transport streams (TS) received
|
|
from terrestrial/cable/satelite in order to support the different topologies of
|
|
the end product, as it may be deployed in many different topologies.
|
|
In addition, the active topology may change according to various factors such as
|
|
broadcast technology and/or conditional access system.
|
|
|
|
2. CI function: acting as a common interface, complying with both PC Card and
|
|
CI/+ specifications.
|
|
|
|
The TSC driver has two different interfaces, one for each function.
|
|
|
|
Hardware description
|
|
====================
|
|
The TSC HW contains the TSC core, and uses the VBIF unit (IOMMU) which is part
|
|
of the broadcast subsystem HW.
|
|
|
|
Mux function:
|
|
-------------
|
|
The TSC can receive transport streams from:
|
|
a. Two Transport Stream Interfaces (TSIFs) 0 or 1, connected to two external
|
|
demods or to external bridge.
|
|
b. One TSIF from an integrated demod.
|
|
|
|
The TSC can route TS from any of the above TSIFs to an external CICAM, using a
|
|
software configurable mux.
|
|
The TSC can route TS from any of the above TSIFs, and TS received from the CI
|
|
Conditional Access Mudule (CICAM) to two TSIF outputs (0 or 1), using two
|
|
software configurable muexes.
|
|
The CICAM input and outputs are also managed via two additional TSIFs: TSIF-out
|
|
to the CAM, and TSIF-in from the CAM.
|
|
|
|
CI function:
|
|
------------
|
|
The common interface is composed of:
|
|
1. Card detection logic: the TSC notifies the SW of any change in the card
|
|
detection status (via HW interrupt).
|
|
|
|
2. Control interface used to send/receive the CI messages (APDUs), supporting
|
|
data transmission in two formats:
|
|
a. Single byte transactions: to/from the attribute memory space of the CAM and
|
|
the command area of the CAM.
|
|
b. Buffer transactions: to/from the command area of the CAM, using a
|
|
configurable buffer size of 1k bytes-64k bytes. This enables transferring
|
|
large chunks of data between the CAM and applications.
|
|
The data buffer resides in the external memory and the interface to the
|
|
memory is done through BCSS VBIF.
|
|
The TSC uses PCMCIA interface to interact with the CAM.
|
|
|
|
The following diagram provides an overview of the TSC HW:
|
|
+-------------------------------------------------------------------------+
|
|
| |
|
|
| +------------------------------+ |
|
|
| +-----------+ | TSC Core --. | |
|
|
| |Ext. TSIF 0+------------+------------>| \ | +-----------+ |
|
|
| +-----------+ | +-----|------------>|Mux)----->TSPP TSIF 0| |
|
|
| +-----------+ | | +--|------------>| / | +-----------+ |
|
|
| |Ext. TSIF 1+------| | | +->--' | |
|
|
| +-----------+ | | | | | --. | |
|
|
| | | | +----------|->| \ | +-----------+ |
|
|
| +-----------+ | +--|--|-+--------|->|Mux)----->TSPP TSIF 1| |
|
|
| |Int. TSIF +---------+--|-|-+------|->| / | +-----------+ |
|
|
| +-----------+ | | | | +->--' | |
|
|
| | | | | | | |
|
|
| | | | | | | |
|
|
| |+------+(v-v-v--) | +-----+| |
|
|
| ||Card | \ Mux / | |CI/+ +---Data-Interface--+ |
|
|
| ||detect| `---' | +----++| | |
|
|
| |+-^-^--+ | | | | | |
|
|
| +--|-|-------|-------|-------|-+ +------+----+ |
|
|
| | | | | | | VBIF | |
|
|
| | | +-----v--+ +--+----+ | | | |
|
|
| | | |TSIF-Out| |TSIF-In| | +-----------+ |
|
|
| | | +-----+--+ +--^----+ | |
|
|
| | | | | | |
|
|
| ++-+-------v-------+-------++ |
|
|
| | CICAM | |
|
|
| | | |
|
|
| +---------------------------+ |
|
|
+-------------------------------------------------------------------------+
|
|
|
|
Software description
|
|
====================
|
|
The TSC Linux kernel driver manages the TSC core. It is a standard Linux
|
|
platform device driver. It can be configured as a loadable or built-in kernel
|
|
module. The driver is supported only in platforms that contain the TSC HW.
|
|
|
|
The TSC driver uses ION driver to control the IOMMU and map user-allocated
|
|
buffers to the TSC IOMMU domain.
|
|
|
|
The driver provides an abstraction of the TSC HW functionality for user-space
|
|
clients via two separate interfaces: tsc_mux and tsc_ci. These interfaces may
|
|
be used by upper layers to utilize the TSC HW for routing the TS and supporting
|
|
the Common Interface specification.
|
|
|
|
Driver initialization
|
|
---------------------
|
|
The driver's probe function is invoked if there is a matching device tree node.
|
|
The probe function gets the required memory resources (i.e., register address
|
|
spaces) and maps them to kernel space for the driver's use.
|
|
The probe function also requests the required IRQs, GPIOs and clocks, and gets
|
|
the TSC IOMMU domain. The probe function also disables the TSIFs input.
|
|
Finally, the function creates two character device drivers: "tsc_mux","tsc_ci".
|
|
|
|
See API description in interface section.
|
|
|
|
Data paths
|
|
-----------
|
|
The TSC does not process the TS data received from the TSIFs. It just manages
|
|
the routing of that data.
|
|
|
|
Control paths - Mux function
|
|
----------------------------
|
|
Example for routing the TS from external demod TSIF 0 to the CAM, and from the
|
|
CAM to TSIF 1 of the TSPP:
|
|
|
|
struct tsc_route tsif_cam = {TSC_SOURCE_EXTERNAL0, TSC_DEST_CICAM};
|
|
struct tsc_route cam_tspp = {TSC_SOURCE_CICAM, TSC_DEST_TSPP1};
|
|
int mux_fd, ret;
|
|
enum tsc_source tsif0 = TSC_SOURCE_EXTERNAL0;
|
|
enum tsc_source cam = TSC_SOURCE_CICAM;
|
|
|
|
/* opening Mux char device */
|
|
mux_fd = open("/dev/tsc_mux0");
|
|
|
|
/* Configure the CAM mux to route TS from external demod TSIF 0: */
|
|
ret = ioctl(mux_fd, TSC_CONFIG_ROUTE, &tsif_cam);
|
|
|
|
/* Configure the TSPP TSIF 1 mux to route TS from CAM: */
|
|
ret = ioctl(mux_fd, TSC_CONFIG_ROUTE, &cam_tspp);
|
|
|
|
/* Enabling the external demod TSIF 0, and the CAM TSIF-in and TSIF-out */
|
|
ret = ioctl(mux_fd, TSC_ENABLE_INPUT, &tsif0);
|
|
ret = ioctl(mux_fd, TSC_ENABLE_INPUT, &cam);
|
|
|
|
close(mux_fd);
|
|
|
|
Control paths - CI function
|
|
---------------------------
|
|
Example for writing a buffer to the CAM command area:
|
|
|
|
Assumptions:
|
|
1. The user allocated a buffer using ION driver and wrote to that buffer.
|
|
Also, retrieved the ion fd of that buffer and saved it to:
|
|
int buffer_fd;
|
|
2. The user already performed buffer size negotiation with the CAM according to
|
|
CI/+ specification, and had set the CAM size register with the buffer size. This
|
|
size is saved to: int size;
|
|
3. The user decided about the time the user wants to wait for the data
|
|
transmission.
|
|
struct tsc_buffer_mode buff_params = {buffer_fd, size, timeout};
|
|
int ret;
|
|
|
|
/* Perform a blocking write buffer transaction for at most timeout */
|
|
ret = ioctl(fd, TSC_WRITE_CAM_BUFFER, &buff_params);
|
|
/* ret indicate whether the transaction succeeded */
|
|
|
|
Example for SW reset to the CAM (according to CI/+ specification):
|
|
struct single_byte_mode cmd_params = {1, RS bit set, timeout};
|
|
struct single_byte_mode stat_params = {1, not initialize, timeout};
|
|
int ci_fd, ret;
|
|
u8 data;
|
|
|
|
/* opening CI char device */
|
|
ci_fd = open("/dev/tsc_ci0");
|
|
|
|
/* Setting the RS bit of the CAM command register */
|
|
ret = ioctl(ci_fd, TSC_WRITE_CAM_IO, &cmd_params);
|
|
|
|
/* Polling the FR bit of the CAM status register */
|
|
ret = ioctl(ci_fd, TSC_READ_CAM_IO, &stat_params);
|
|
data = stat_params.data;
|
|
while (data & FR_BIT_MASK) {
|
|
ret = ioctl(ci_fd, TSC_READ_CAM_IO, &stat_params);
|
|
data = stat_params.data;
|
|
}
|
|
|
|
close(ci_fd);
|
|
|
|
Design
|
|
======
|
|
The TSC driver is a regular Linux platform driver designed to support the
|
|
TSC HW available on specific SoCs.
|
|
|
|
The driver provides two user-space APIs: tsc_mux that allows the client full
|
|
control over the configuration of the TS routing, and tsc_ci that enables the
|
|
client to implement the Common Interface in front of the CAM. It does so while
|
|
encapsulating HW implementation details that are not relevant to the clients.
|
|
|
|
The driver enforces HW restrictions and checks for input parameters
|
|
validity, providing a success or failure return value for each API function:
|
|
0 upon success or negative value on failure. Errno parameter is set to indicate
|
|
the failure reason.
|
|
However, the driver does not enforce any high-level policy with regard to the
|
|
correct use of the TSC HW for various use-cases.
|
|
|
|
Power Management
|
|
================
|
|
The TSC driver prevents the CPU from sleeping while the HW is active by using
|
|
wakeup_source API. When there are no open devices the driver releases the wakeup
|
|
source. In a similar manner, the driver enables the HW clocks only when needed.
|
|
|
|
SMP/multi-core
|
|
==============
|
|
The driver uses a spinlock to protect accesses to its internal databases,
|
|
for synchronization between user control API and kernel interrupt handlers.
|
|
|
|
The driver uses a mutex for all the Mux operations to synchronize access to the
|
|
routing internal databases. The driver uses another mutex for all the CI
|
|
operations to synchronize data sent and received to and from the CAM.
|
|
|
|
Security
|
|
========
|
|
Although the TSC is the bridge the external conditional access module, it has no
|
|
security aspects. Any protection which is needed is performed by the upper
|
|
layers. For example, the messages which are written to the CAM are encrypted.
|
|
Thus the TSC accesses only non-protected, HLOS accessible memory regions.
|
|
|
|
Performance
|
|
===========
|
|
Control operations are not considered as performance critical.
|
|
Most of the control operations are assumed to be fairly uncommon.
|
|
|
|
Interface
|
|
=========
|
|
Kernel-space API
|
|
----------------
|
|
The TSC driver does not provide any kernel-space API, only a user-space API.
|
|
|
|
User-space API
|
|
----------------
|
|
Open: upper layer can open tsc_mux device and/or tsc_ci device.
|
|
Release: close the device and release all the allocated resources.
|
|
Poll: two different functions- one for Mux, one for CI. The Mux poll wait for
|
|
rate mismatch interrupt. The CI poll waits for card detection HW interrupt.
|
|
The rate mismatch interrupt is not cleared in the interrupt handler because it
|
|
will signal again all the time. Therefore it is cleared via a specific ioctl
|
|
that upper layer can use after the problem is solved. Additionally, the
|
|
interrupt is cleared when the card is removed.
|
|
ioctl: two functions, one for mux and one for ci. The ioctl are specified below.
|
|
|
|
TSC Mux - routing the TS:
|
|
-------------------------
|
|
enum tsc_source {
|
|
TSC_SOURCE_EXTERNAL0,
|
|
TSC_SOURCE_EXTERNAL1,
|
|
TSC_SOURCE_INTERNAL,
|
|
TSC_SOURCE_CICAM
|
|
};
|
|
enum tsc_dest {
|
|
TSC_DEST_TSPP0,
|
|
TSC_DEST_TSPP1,
|
|
TSC_DSET_CICAM
|
|
};
|
|
|
|
struct tsc_route {
|
|
enum tsc_source source;
|
|
enum tsc_dest dest;
|
|
};
|
|
|
|
#define TSC_CONFIG_ROUTE _IOW(TSC_IOCTL_BASE, 0, struct tsc_tspp_route)
|
|
#define TSC_ENABLE_INPUT _IOW(TSC_IOCTL_BASE, 1, enum tsc_source)
|
|
#define TSC_DISABLE_INPUT _IOW(TSC_IOCTL_BASE, 2, enum tsc_source)
|
|
|
|
These 3 IOCTLs control the 3 muxes that route the TS, and enable/disable the
|
|
TSIFs input.
|
|
|
|
TSC Mux - configuring the TSIFs:
|
|
--------------------------------
|
|
enum tsc_data_type {
|
|
TSC_DATA_TYPE_SERIAL,
|
|
TSC_DATA_TYPE_PARALLEL
|
|
};
|
|
enum tsc_receive_mode {
|
|
TSC_RECEIVE_MODE_START_VALID,
|
|
TSC_RECEIVE_MODE_START_ONLY,
|
|
TSC_RECEIVE_MODE_VALID_ONLY
|
|
};
|
|
|
|
struct tsc_tsif_params {
|
|
enum tsc_source source;
|
|
enum tsc_receive_mode receive_mode;
|
|
enum tsc_data_type data_type;
|
|
int clock_polarity;
|
|
int data_polarity;
|
|
int start_polarity;
|
|
int valid_polarity;
|
|
int error_polarity;
|
|
int data_swap;
|
|
int set_error;
|
|
};
|
|
|
|
#define TSC_SET_TSIF_CONFIG _IOW(TSC_IOCTL_BASE, 3, struct tsc_tsif_params)
|
|
|
|
This IOCTL enables configuring a specific TSIF with all possible configurations.
|
|
|
|
TSC Mux - clearing rate mismatch interrupt
|
|
------------------------------------------
|
|
|
|
#define TSC_CLEAR_RATE_MISMATCH_IRQ _IO(TSC_IOCTL_BASE, 4)
|
|
|
|
This IOCTL is used for clearing the interrupt, which is not done automatically
|
|
by the driver.
|
|
|
|
TSC CI - CAM configuration:
|
|
---------------------------
|
|
enum tsc_cam_personality {
|
|
TSC_CICAM_PERSONALITY_CI,
|
|
TSC_CICAM_PERSONALITY_CIPLUS,
|
|
TSC_CICAM_PERSONALITY_PCCARD,
|
|
TSC_CICAM_PERSONALITY_DISABLE
|
|
};
|
|
enum tsc_card_status {
|
|
TSC_CARD_STATUS_NOT_DETECTED,
|
|
TSC_CARD_STATUS_DETECTED,
|
|
TSC_CARD_STATUS_FAILURE
|
|
};
|
|
|
|
#define TSC_CICAM_SET_CLOCK _IOW(TSC_IOCTL_BASE, 5, int)
|
|
This IOCTL sets the clock rate of the TS from the TSC to the CAM
|
|
|
|
#define TSC_CAM_RESET _IO(TSC_IOCTL_BASE, 6)
|
|
This IOCTL performs HW reset to the CAM
|
|
|
|
#define TSC_CICAM_PERSONALITY_CHANGE \
|
|
_IOW(TSC_IOCTL_BASE, 7, enum tsc_cam_personality)
|
|
This IOCTL configures the PCMCIA pins according to the specified card type.
|
|
|
|
#define TSC_GET_CARD_STATUS _IOR(TSC_IOCTL_BASE, 8, enum tsc_card_status)
|
|
This IOCTL queries the card detection pins and returns their status.
|
|
|
|
TSC CI - Data transactions:
|
|
---------------------------
|
|
struct tsc_single_byte_mode {
|
|
u16 address;
|
|
u8 data;
|
|
int timeout; /* in msec */
|
|
};
|
|
struct tsc_buffer_mode {
|
|
int buffer_fd;
|
|
u16 buffer_size;
|
|
int timeout; /* in msec */
|
|
};
|
|
|
|
#define TSC_READ_CAM_MEMORY \
|
|
_IOWR(TSC_IOCTL_BASE, 9, struct tsc_single_byte_mode)
|
|
#define TSC_WRITE_CAM_MEMORY \
|
|
_IOW(TSC_IOCTL_BASE, 10, struct tsc_single_byte_mode)
|
|
#define TSC_READ_CAM_IO \
|
|
_IOWR(TSC_IOCTL_BASE, 11, struct tsc_single_byte_mode)
|
|
#define TSC_WRITE_CAM_IO \
|
|
_IOW(TSC_IOCTL_BASE, 12, struct tsc_single_byte_mode)
|
|
#define TSC_READ_CAM_BUFFER \
|
|
_IOWR(TSC_IOCTL_BASE, 13, struct tsc_buffer_mode)
|
|
#define TSC_WRITE_CAM_BUFFER \
|
|
_IOW(TSC_IOCTL_BASE, 14, struct tsc_buffer_mode)
|
|
|
|
These IOCTLs performs a read/write data transaction of the requested type.
|
|
|
|
Driver parameters
|
|
=================
|
|
The TSC module receives one parameter:
|
|
tsc_iommu_bypass - 0 for using the VBIF, 1 for not using it. Not using the VBIF
|
|
is a debug configuration.
|
|
|
|
Config options
|
|
==============
|
|
To enable the driver, set CONFIG_TSC to y (built-in) or m (kernel module)
|
|
in the kernel configuration menu.
|
|
|
|
Dependencies
|
|
============
|
|
The TSC driver uses the ION driver for IOMMU registration and buffer
|
|
mapping to BCSS VBIF.
|
|
|
|
User space utilities
|
|
====================
|
|
None.
|
|
|
|
Other
|
|
=====
|
|
None.
|
|
|
|
Known issues
|
|
============
|
|
None.
|
|
|
|
To do
|
|
=====
|
|
None.
|